I’ll admit it, for the longest time I had no idea that a lot of thought goes into writing functions. For me, creating a function meant writing a block of code that is reusable. It’s a simple idea and it stuck with me, function == reusable code.
I had no notion of structure or length or meaning. With time, as the project grew, things started to look like long scripts. There was almost a pattern to these long functions with code and comments interleaving with each other.
Long functions are very costly:
- Hard to read and remember
- Hard to test and debug
- Conceal business rules
- Hard to reuse and lead to duplication
- Have a higher probability to change
- Can’t be optimized
- Obsolete comments
Long functions by design have very low cohesion and know too much about the system, high coupling. This is orthogonal to the fundamentals of software design which say components should have high cohesion and how coupling.
Single Level of Abstraction Principle(SLAP)
It’s difficult to judge if a function is long by counting the number of lines. Is 50 too long? What about 25 or 10? How small is small enough? This is where SLAP comes into play.
Code within a given segment/block should be at the same level of abstraction.
So the question is not how long a function is, it’s what is the level of abstraction of a function? A function should not mix different levels of abstraction. For ex. a function doing form validation should not make I/O calls.
As a thumb rule:
Functions should do just one thing, and they should do it well. — Robert Martin
Functions that do more than one thing face the same drawbacks as long functions. This rule becomes even more obvious when you start testing your code. It is so much simpler to test functions that do one thing as you don’t have to worry about all the complex permutations and combinations.
Compose Method Pattern
Often times when you have comments explaining blocks of code, they are candidates for function extractions.
As Kent Beck said, divide your program into functions that perform one identifiable task. Keep all of the operations in a function at the same level of abstraction. This will naturally result in programs with many small functions, each a few lines long.