A little housekeeping before I start the essay:
Chapter 3 of Executable Specifications is available! Please let me know what is unclear.
I’m working on Chapter 4: Composition Lens. That’s where it gets algebraic.
And now for the essay:
I used to study Tai Chi pretty seriously. I would practice a lot and take lessons. There are a lot of classical texts on Tai Chi, but once you get beyond the basic texts that detail the movements, the texts read like incomprehensible poetry.
Here’s an excerpt:
Full and empty
should be clearly differentiated.
At any place where there is emptiness,
there must be fullness;
Every place has both emptiness and fullness.
What I found was that the more I practiced and the better I got, the more I could understand that poetry. They were filled with little descriptions of the subtle experiences you get when you start to pay attention to your body while doing slow, relaxed movements. It was quite enjoyable to read that someone was having the same experience hundreds of years ago.
However, the more I thought about it, the less I liked it. These classics might let you know you’re progressing down the path, but they are not teaching you. It’s the practice itself that is increasing your knowledge. The poems are only comprehensible if you’ve already gained the skill. They don’t impart the skill themselves. But worse, they mystify the process.
And that’s what I think software design advice is like. People list principles and guidelines, but they have so many exceptions to them, they’re only useful if you already know design intuitively through years of practice.
Concrete and abstract must both be present.
Concrete code makes clear what it does.
Abstract code makes clear why it does.
Write abstract code that is concrete.
Write concrete code that is abstract.
This is the way.
Bogus.
Software design teachings are often like mystical advice. As I’ve matured as a programmer, the advice sounds less like sage teachings and more like people grasping at straws. Even though I hear some truth in it, I cringe. I often don’t disagree with the spirit of the advice, merely its presentation. I imagine sending the blog post or conference talk to a friend. Will they see what I see?
I’m guilty of mystifying software design, too. I’m sympathetic to the difficulty of teaching programming beyond the basic level. I try to define my terms, use them consistently, and not call things rules or principles when they’re heuristics. But I often fail, so I’m not judging the people. I am only striving to do better personally and as an industry.
The antidote to mystical design advice is to go deeper. We must get closer to a root cause—something with explanatory power—and use that instead of the frothy pseudo-explanations we find in mysticism. James Koppel calls bad explanations “citrus advice,” referring to the explanation that citrus prevents scurvy (it doesn’t). Where can we look to find deeper explanations?
The problem is that we are trying to give advice about software design while merely speaking about the code. We say, “Functions shouldn’t be too long,” “Implement an interface because maybe the code will change,” or “Use decorators if you have too many classes.” I think it’s really hard to say anything meaningful about how to write good code when you’re just talking about the code. Code is about something. You have to mention that at least a bit.
For instance, let’s say you’re adding a level of indirection to your code—an interface in front of a class. Is that good or bad? It’s impossible to say. Not only is there all of the context of the rest of the codebase, but there’s also the domain you are implementing within—the real-world context. How can you judge the usefulness of the new interface without reference to the real world?
However, with that context, we can at least ask good questions:
Does the indirection solve a domain problem?
Does the indirection correspond to a domain concept?
Does the indirection modularize a known source of volatility?
We don’t know how to teach software design. We’re still grasping at straws. 99% of software design advice is a zen finger pointing at the moon. We can do better. We can find ways of explaining things that clarify instead of mystify.
This is why I got a reputation for saying "It Depends!" in response to nearly every design question people ask me :)