We’ve spent some time on the thinking-knee, but i’m not quite done with it yet. Let’s narrow our focus for a minute, to matters strictly around code & coding.
Programmers have been thinking directly & indirectly about ways to evade or at least mitigate the effect of the non-linear thinking knee more or less forever.
Dijkstra’s famout short paper, "Go To Statement Considered Harmful", from ’68, is an early example. He doesn’t invoke the knee explicitly, but the harm he’s speaking of is expressly that it makes it hard for humans to think about the code. "structured programming," the movement surrounding this paper, is almost entirely an effort to start minimizing and organizing the pieces of code we have to think about.
Tho some of its tenets have been softened over the years, the gist of structured programming is nearly invisible to us: it is the air we breathe. Most of us take single-entry (not so much single-exit) named functions taking parameters & returning values entirely for granted.
So people who theorize about the human act of coding have been wrestling with the thinking knee in a variety of ways for a long time. The agilists have forwarded this movement, but we didn’t start it and we’re not done with it yet.
Not all such efforts have been successful by the way, and one illustration of this might actually help us here: simonyi’s now much-derided hungarian notation. (for those who didn’t suffer through this, hungarian notation is the practice of pre-pending type info to variable names, so iCount is an integer, afPoints an array of floats, or such-like.) the impulse — help geeks think about their code — was good. The belief that providing more info about a variable whose declaration was very far away, not so good.
From a thinking knee perspective, hungarian notation says/does nothing about the piece count, it just attaches extra info to each piece. The result may have been slightly net-positive, tho that’s debatable. In the end, hungarian was discarded because it wasn’t free and it didn’t attack the main problem: piece count itself.
So how do we attack the piece count to keep from loading ourselves past the thinking knee? (speaking strictly about coding for today, we’ll zoom back out later.) in Miller’s even more famous paper, "The Magical Number Seven Plus Or Minus Two" he posits that the human thinking knee happens when we get up between 5 and 9 pieces.
- Aside #1: you really ought to read this paper, as it is not only fascinating in its conclusions, but is both charming & rather funny. It puts to rest thoroughly the idea that science writing can’t be great writing.
- Aside #2: most modern psychologists would tell you that miller was wrong: the 60 years since have produced hundreds of experiments suggesting he over-estimated, and the real value is between 4 and 7 pieces.) but if the thinking knee happens around 7 pieces, how do human thinkers do anything? How do programmers write programs containing literally hundreds of thousands of pieces?
The trick is called "chunking". There are a lot of subtleties and sub-tricks involved, but the colloquial version looks like this: "put pieces in boxes. When you’re in the box, only think about it’s contained pieces. When you’re out, treat the whole box as one piece. Chunking works. In some circumstances, it works very well, in others, less so. One way to see the last 40 years of coding theory is to see it as the working out of more & better ways to chunk things.
This is not an "agile" thing, not yet. Single-entry structured functions are chunks. Objects are chunks. The horizontal layers of layered architecture, the vertical stripes of microservices, the package/module/namespace stuff in most modern languages: all chunk facilitation. They are all about cheating the thinking knee by using chunks to get the piece count low enough that we can think effectively.
So agile coding practice isn’t an abrupt departure from the last decades of mainstream coding practice, but a continuation and extension of it. It is the latest of many waves whose focus is the thinking knee.
So much focus on names? Strong names facilitate chunking. SRP and most of SOLID? Clean boundaries between chunks.
What even is refactoring? "factor" is just another name for chunk. Refactoring is rearranging chunks without changing function. There’s no possible reason for it but to facilitate chunking.
The microtests we prefer in TDD? The way we test interactively, test-code-test-code-test-code? Directly about keeping piece counts small. (hard-TDD’ers, like myself, would add that TDD’s view of tests & testability as first-class participants in design is actually itself a way to encourage if not force good chunking.)
So. Where are we?
Some problems are non-linear. Action cost goes up faster than piece count, sometimes so much faster it creates knees that we very much want to avoid. Human thinking has such a knee. We use chunking to sidestep or mitigate its effects. Coding practice has been about keeping programmers below that knee for at least 4 decades through facilitating that chunking and agile coding practice is in many ways an extension and retrenchment of this movement to ease the chunking process.
We’re almost there, and i’m relieved cuz i’m ready to be done with this topic for a while, but there’s one more piece, for next time: how does agile practice address the thinking knee in contexts around and beyond coding itself?