| Well, inlining by the compiler would be expected but we do not only write the code for the machine but also for another human being (that could be yourself at another moment of time of course). Splitting the code into smaller functions does not automatically warrant a better design, it is just one heuristic. A naive implementation of the principle could perhaps have found a less optimal solution function positiveInt max(positiveInt value1, positiveInt value2)
return value1 > value2 ? value1 : value2
function positiveInt total(positiveInt value1, positiveInt value2)
return value1 + value2
function positiveInt calcMeaningOfLife(positiveInt[] values)
positiveInt total = 0
positiveInt max = 0
for (positiveInt i=0; i < values.length; i++)
total = total(total, values[i])
max = max(max, values[i])
return total - max
Now this is a trivial example but we can imagine that instead of max and total we have some more complex calculations or even calls to some external system (a database, API etc).When faced with a bug, I would certainly prefer the refactoring in the GP comment than one here (or the initial implementation). I think that when inlining feels strictly necessary then there has been problem with boundary definition but I agree that being able to view one single execution path inlined can help to understand the implementation. I completely agree that naming and abstractions are perhaps two most complicated problems. |
That's the thing, isn't it? Various arguments have been raised all across this thread, so I just want to put a spotlight on this principle, and say:
Myself, based on my prior experience, find code with few larger functions much more readable than the one with lots of small functions. In fact, I'd like a tool that could perform the inlining described by the GP for me, whenever I'm working in a codebase that follows the "lots of tiny functions" pattern.
Perhaps this is how my brain is wired, but when I try to understand unfamiliar code, the first thing I want to know is what it actually does, step by step, at low level, and only then, how these actions are structured into helpful abstractions. I need to see the lower levels before I'm comfortable with the higher ones. That's probably why I sometimes use step-by-step debugging as an aid to understanding the code...