One part of coding style that I’ve become particularly opinionated about is that of making functions short. Rather than engage in tolerant and lax debates in person, I thought it best to write about my opinions on my blog where they can’t be questioned (except in the comments section, which I moderate).
Without further adieu, here are my list of reasons why I think that functions should be created at will and with a short amount of logic:
Ideal code is that which requires no comments. A comment indicates that the code is confusing and requires additional explanation to be understood. My own personal goal while coding is to only leave comments when explaining the high level solution of what’s going on. In order to achieve this, one pre-requisite is to name variables appropriately, but the other part of this is to routinely abstract away logic. If I ever find myself writing something that requires an explanation, it then generally makes sense to compartmentalize it into its own function where the name of the function provides the explanation of what’s happening.
Easier to Test
When functions are built strictly with inputs and outputs and a direct route from one to the other, there are fewer edge cases to consider when testing that particular function, and it’s otherwise easier to write tests when there is no tangential behavior within the function. Furthermore, if we have a function A that’s composed of nothing but helper functions B, C, and D, then we can test most of the results for function A by validating all of its helper functions. Additionally, when modifying any of those helper functions, it’s again easier to validate tests. Now when we make changes to any related code, we can make those changes with ease and with confidence.
Modularity – Easier to Debug and Maintain
If I need to go check the oil in my car, I know that all I need to do is to find that stick thingy with the tea kettle looking picture and pull that out of the hole (I’m also the son of a mechanic, so I’m quite handy, but I digress).
Similarly, if I’m trying to debug or modify code that I didn’t write, it’s much easier to isolate where a change needs to occur. If the code is already written in such a way with modular pieces, then I don’t necessarily need to understand what’s going on elsewhere in the code. I just have to find the proper place to modify the appropriate inputs and outputs to make the changes.
If we assume the inverse, then I might need to read and parse through hundreds of lines of code to first understand exactly what is happening. Moreover, after I make the change, I will next have to ensure that I didn’t break something where my change is still in scope for hundreds more lines.
Also, I’ve never caught myself saying, Man, I wish this code were less modular.
Oftentimes while I’m coding and making a point to abide by my own goal of constantly abstracting away logic into small bits, I conveniently find that some of the work I’m about to do has already been written in one of those helper functions. Otherwise, I may find that the logic I’m implementing is similar to previously written code, and in that case, I can modify the appropriate helper function to take additional inputs.
This ends up making the entirety of the program we’re writing smaller even with the extra lines devoted to function definitions, and I’d also argue that it makes the code easier to write. Another huge advantage with code re-use is that when we need to make a change, we only need to make that change in exactly one place.
I checked out some other debates on this topic on the internets that might be worth a google, and there might be some nuanced counterarguments to my claim. My overall point here is in very general terms. Questions may be raised about a function being TOO short (for example, when a function is a single line whose name is simply the contained logic written out in English). My point here is to attempt to curb the behavior of writing lines and lines of sequential commands with no helper functions.
To extend this topic even further, I was introduced to Sandi Metz’ Rules For Developers from my favorite software Podcast, Giant Robots Smashing Into Other Giant Robots. The goal, of course, is to one day develop Scott Lobdell’s Rules For Developers and Weightlifters.