Without peeking, I’m willing to bet your function bodies are too fat.
Your procedures are too big. They contain too much detail, too many code blocks, too many paths through the code. They may have too many levels of “ifs”. They often have too many passed parameters. And, they have too many lines of code. Too fat.
Take a good look at your code. The following traits are signs of fat. Does the function/procedure contain more than 40 lines of code or 60 lines of text? Are there more than 4 passed parameters? Does the function contain more than one independent code loop? Does the function have more than 12 different unique paths through the logic? Don’t feel “too” embarrassed; most programmers tend to write large functions (and procedures). We haven’t been taught to give importance to small functions and, with few exceptions, most educators and gurus do not stress “lean” code.
Of course there are situations that require a lot of lines of code. Sometimes a large switch statement is needed. (More than once I’ve written switch statements containing over 100 case statements.) Occasionally you need loops within loops to walk-through multiple dimension arrays. Every program has its own unique requirements; sometimes those requirements mandate a very large function. But most don’t.
There always seems to be some push-back to coding small functions. Creating the interface for several small functions is more work than creating the interface for one larger function. There are many who perpetuate the myth that procedure call overhead is large; they claim to write large procedures to make their code more efficient. Of course, all of us have experienced procedures that started small, but grew over the project. Factoring a large code procedure into several smaller ones is just not fun. Who has time to do more work on “running” code?
Yet, we programmers need to understand that fat code is a real problem. Fat functions are harder to test; every logic path through the code must be checked for proper behavior. (Of course you always do this; right?) Fat functions are harder to update. They are harder to review. They are even harder to document; try writing concise documentation of a function that has 50 different outcomes depending on the values of parameters and/or static variables. (By-the-way, another way to determine a function is too fat is to try to describe the function to others without using the word “And”; “And” is a warning flag.)
So what do you do? An obvious solution is to simply take pieces of code from the fat function and make them subroutines. Most programmers think of this, but then ask themselves does this really make things better? The convenient answer we tell ourselves is ‘No’, so no effort is made to de-compose the procedure. After all, does the carpenter’s job get easier if he cuts every large board in half before nailing it?
This is wrong thinking. The carpenter analogy does not apply because it views the programming process as one of building functions and then breaking them into pieces when they get too big. Creating lean functions is not about taking the large procedures apart. It’s really about building code with the intent of keeping the procedures small and simply structured. This means recognizing code that should be gathered into a subroutine during the construction process and making that happen.
So what am I suggesting? First, programmers should begin with acceptance; we need to acknowledge that writing lean code is a critical part of the job. It is not a task to be done “next week”. Second, pay attention while writing the code for the point when a procedure has crossed the line and needs to be better structured – then do it. Third, realize that greater danger is present when adding a new feature; we need to resist the urge to do a “quick-and-dirty” code patch.
Finally, become an advocate for lean code. When reviewing code for others speak up. Be willing to say “Your function bodies are too fat.”