Clean Coders Episode 3: Functions
Note: In this post I switch between using the words function & method because the video uses function but I usually use method. For the purposes of this post they mean the same thing.
“Your functions should all be about four lines long”
That’s the bold advice offered up in the third episode of Clean Coders, and if you follow the rules laid out in the episode it seems entirely possible to keep your methods nice and small. The primary rule is to “extract ‘til you drop” so that every function does only one thing and does it well.
But why should your methods even be that short? I’ll admit that when I first read this advice in Clean Code I was pretty resistant to it. As a newcomer I usually found it quite a bit easier to read big functions as opposed to having to scroll up and down a page and track behavior through multiple methods and even between multiple classes. It just seemed simpler to have everything in one spot, and it was definitely easier to write it all in one place.
However, now that I’ve been working with more and more code I can understand why it’s so important to have short functions- and for me it all comes down to one reason, and when shortening those functions it’s crucial that you follow one rule.
The Reason: Maintenance
My episode two report included the quote ““the true cost of software is in maintenance”, and the more I work on code and think about how I’d code out different ideas I realize just how true this is. As excited as a programmer might be about some whiz-bang masterpiece of code they are writing, there will inevitably be some new requirement and it will have to change. The simpler your functions are, the easier they will be to change.
The Rule: Naming
Uncle Bob makes a good point of discussing just how important naming these new short functions are, but I don’t think he’s blatant enough (and maybe I feel this way because I’m still no good at naming). There should have been a big flashing message that "You have to name your small functions well or you’ll confuse the next person looking at your code even more”. However, when a function is named well I don’t even have to go digging around to look at the other functions it references— and if I do, I know what behavior I’m looking for. Here’s a short example off the top of my head (that actually does too much as a function), but I’ll use it strictly as a naming example:
def charge_late_fees(book)
calculate_late_fee(book) if book.overdue?
end
This is very easy to read and I have a pretty good hunch what the charge_late_fee
and overdue?
functions are going to do.
On the other hand, let’s look at the following:
def charges(book)
amount(book) if book.past_due
end
Here I have no idea what the 'charges’ are for, what 'amount’ refers to and what time frame 'late’ refers to. Is this a charge to a writer if there rough draft wasn’t the right amount of pages by a deadline? Or a charge to a dealer if they hadn’t paid for a certain amount of books on time? I’d definitely have to do some investigating.
Overall this was another great episode and includes A LOT of code examples. There’s even three additional screencasts for almost two extra hours of refactoring.