> The real enemy addressed by inlining is unexpected dependency and mutation of state, which functional programming solves more directly and completely. However, if you are going to make a lot of state changes, having them all happen inline does have advantages; you should be made constantly aware of the full horror of what you are doing. When it gets to be too much to take, figure out how to factor blocks out into pure functions (and don.t let them slide back into impurity!).
Some years ago at job foo I wrote a Ruby library that was doing some stuff. Time was of the essence, I was a one-man team, and the trickiness of it required a clear understanding of the details, so I wrote a single ~1000 LOC file comprising of the entirety of the namespace module of that library, with but a couple or three functions.
Then a new hire joined my one-man team. I said: apologies for this unholy mess, it's overdue for a refactoring, with a bunch of proper classes with small methods and split in a few files accordingly. They said: not at all, the code was exceptionally clear; I could sit and understand every bit of it down to the grittier critical details in under an hour, and having seen it written this way it is obvious to me that these details of interactions would not have been abstracted away, but obscured away.
I have worked with many developers and I have seen them follow two distinct paths when encountering complex code.
There's one camp that wants to use abstractions and names, and there's another (in my experience, smaller) camp which prefers to have as few abstractions as possible, and "every gritty detail visible".
I think both strategies have advantages and disadvantages. The group that likes abstractions can "ignore parts of the code" quickly, which potentially makes them "search" faster. If there's a bug that needs fixing, or a new feature that needs to be added, they will reach the part of the code that will need modifications faster.
The detail-oriented people can take a bit longer to identify the code that needs modification, but they also tend to be able to make those modifications faster. They also tend to be be great "spelunkers". They seem to have a "bigger cache", so to speak. But it is not infinite. They will eventually not be able to hold all the complexity in their heads, just like the first group. It will just take a bit longer.
I am firmly on the first group and that is how I write my code. I have been fortunate enough to encounter enough people from the other group to know not to diss their code immediately, and to appreciate it for its merits. When working in a team with both kinds of personalities one has to make compromises ("please remove all of these 1-line functions, Jonathan will hate them", and "could you split this 3k lines function into 2 or 3 smaller ones, for easier review?").
Some might consider me part of the "second group", but I'm perfectly fine with abstractions and I create them all the time.
I do however have a problem with indirections that don't really abstract anything and only exist for aesthetical reasons.
Not every function/method is an "abstraction". Having too many one-line methods is as bad as pretending that functions with 2k/3k lines are appropriate in all cases.
Your final ten words of the comment are a perfectly concise explanation of the problem; thank you! And it drives home something I often forget about why code units should do Only One Thing.
Thing is, a lot of developers see long code and think "this is a Bad Thing" because of dogma, but in practice, a lot of developers never actually wrote anything nontrivial like that.
> The real enemy addressed by inlining is unexpected dependency and mutation of state, which functional programming solves more directly and completely. However, if you are going to make a lot of state changes, having them all happen inline does have advantages; you should be made constantly aware of the full horror of what you are doing. When it gets to be too much to take, figure out how to factor blocks out into pure functions (and don.t let them slide back into impurity!).
Some years ago at job foo I wrote a Ruby library that was doing some stuff. Time was of the essence, I was a one-man team, and the trickiness of it required a clear understanding of the details, so I wrote a single ~1000 LOC file comprising of the entirety of the namespace module of that library, with but a couple or three functions.
Then a new hire joined my one-man team. I said: apologies for this unholy mess, it's overdue for a refactoring, with a bunch of proper classes with small methods and split in a few files accordingly. They said: not at all, the code was exceptionally clear; I could sit and understand every bit of it down to the grittier critical details in under an hour, and having seen it written this way it is obvious to me that these details of interactions would not have been abstracted away, but obscured away.