Coupling, cohesion, & the behavior changes we want to make drive what the design should be. The design should support economical, reliable behavior changes. Too much coupling & too little cohesion drives up the cost of features, and not just a little bit, an exponentially lot (for power-law-related reasons we will get to in book 2).
That’s the what. How about when? The word “empirical” in Empirical Software Design is a statement about when. We design when we:
Know what behavior changes are needed
Know as much as we can about the current design
Kerfuffle
I’ve been engaged in this debate about when to design for decades. Slobodan Tanasić has recently argued that earlier is better, that we “laters” are wasting effort. There was some good back & forth, with neither side moved by the other (shocking, I know).
The conversation did lead me to try to visually summarize both sides. To simplify, say we have some combination of software design & feature implementation:
In good Extreme Programming style, we rapidly alternate the two:
So let’s sum up all the effort we spent on design:
(My diagram is giving away the argument.)
Slobodan seems to be saying, “Yeah, but if I do the design earlier, I spend less.” (He doesn’t say it exactly this way. His argument is in terms of repeated re-work.)
It Depends…
The above argument, that investing in design earlier results in greater economic value, depends on hidden assumptions that are seldom true.
NPV. Spending later is equivalent to spending less. If you can defer a design decision long enough, that’s the same as that decision being free from today’s perspective. Earning sooner is also equivalent to earning more. Even if the math worked out that you saved money by designing sooner, you might make more money by earning sooner.
Learning. In the incremental scenario, design happens after experience (hence “empirical”). If you would design differently in the light of experience, the theoretical savings of designing earlier evaporate. If you have to revisit the design either way, the “design later” scenario is an accounting fiction. We just haven’t visualized all of the design investment.
Ergodicity. AKA “survival”. There are software projects that will survive in the incremental scenario because they start earning sooner & they spend later. That same project would have be cancelled if it would have had to wait for revenue to begin. (The power of this effect is a new insight for me, & just too late for it to make it into Tidy First?. Of course.)
Conclusion
Timing software design matters. Not just what design, but when. It’s going to be a tradeoff. Every project is different. But…
“Later” has a bunch of advantages, advantages that seem to be ignored by many skilled software designers. “Sooner”, likewise, has disadvantages that seem to be ignored by many skilled software designers. As a designer, I aspire to consider all the constraints, not just do what is convenient for me.
Deferring choices also means that more alternatives can be considered since it gives them time to mature, catch up or even be created.
I was once asked why i previous project I worked on used RabbitMQ and not Kafka for the messaging system. The answer was pretty simple: Kafka wasn't really a thing at the time.
How have developers changed over time as they gain more experience? Does anyone ever move from design later to earlier? I doubt it.
Also, how much time has been wasted designing for requirements that haven’t been flushed out yet. It’s not just devs who don’t know what to build, users are also often just starting to reason about many parts of the system. Something in their hands helps them to think clearly.