Change-harvesting software design centers "online" brownfield development: change-centric thinking.
Most older sets of design imperatives are based in "offline" greenfield development: build-centric thinking. The differences can — and should — lead to design disagreements.
This week, regular like clockwork, we shoot yet another unarmed Black man in the back, and we quietly arrest a white man carrying a long gun he has just used to kill people. Stay safe. Stay strong. Stay kind. Stay angry. Help us change this. Black lives matter.
The significance of "online brownfield" vs "offline greenfield" is hard to overstate, in all areas of software development, but especially so when we talk about what makes a design "good" or "bad".
In four decades, I’ve read countless books about software design.
I’ve had my favorites, and I’m sure you’ve had yours. Some of my favorites really dont stand the test of time, of course, they were just "right time right place" for me to absorb their ideas and put them into play.
The majority of these books present examples and arguments from a standing start, a blank page, a green field. The author presents a "design problem", more or less rigorously, then shows one or more solutions to it.
We either take the single solution, or rank the several and take the best answer. From there we abstract generalized design principles. Most books do this multiple times with multiple cases, but each case starts with that large blank page onto which we craft our design.
Early in this textual history, the criteria we use to assess & pull abstractions are quite distant from the actual carnival that is professional software development. These works, often quite beautiful, are about assessing the value, one way or the other, of the finished page.
Over time, the texts, at least some of them, get less and less focused on software design "in the mind" and slightly more attentive to software design "in the world". It mostly creeps in around the edges, but it’s there.
Consider an idea like the Dependency Inversion Principle, where we make details depend on abstractions rather than vice-versa. It has some value in most contexts, but the real bang for the buck comes from recognizing you can change the details and not wreck the abstractions.
But why is that important?
It hardly matters if the page is finished. You can argue from elegance or intellectual purity, but it’s not a terribly compelling argument. No. The win here is that the design flexes under change. Explicitly or implicitly, the carnival’s come to town.
Of course, there are masterworks, like Fowler’s Refactoring, or Jeffries’s Nature of Software Development, or three or four of Beck’s books, that actually center their design ideas around change. But, even now, it’s not terribly common.
Anyway, to get back to the starting point, the designs from change-harvesting theory are different from the designs from preceding theories in that they don’t just inject elements of change into the designs, they actually center those elements.
A rough cut at design from a change-harvester: The best design is the one that lets us rapidly field our idea to the market in such a fashion that we can then change that idea in direct response to that market’s dynamics.
It’s like, we want people to move in before the building is finished, before, in fact, it’s even blueprinted. We will harvest three things from that:
- a partial value stream,
- solid guidance for how the architecture should evolve,
- loyalty and confidence of our occupants.
Or think evolution. We can’t evolve a non-existent creature, it has to be in the world. And we can’t evolve a creature that is fixed and final, it has to be changeable. And we can’t design perfection in advance, it has to fit in a world that is changed by its presence.
The difference between classical design theory and modern design theory is exactly this: the changeability of the design is a criterion second only to whether it works at all.
When you study the older texts, you see the changeability criteria gradually slipping in. Ideas like SOLID, even stuff from the ’80s implicitly supports change. But it has a hole, and it’s a big one: It focuses on structural changeability and ignores operational changeability.
What do I mean? Old-school designs make predictions about what is likely to change, and those predictions inform the structure of the design, the look it has on that greenfield page, the boxes and labels and arrows.
What are the three criteria for operational changeability? We went over them a couple of days ago: 1) control, 2) monitoring, and 3) expression.
It’s here if you missed it:
Classical designs don’t isolate "our" code from "their" code, they don’t emphasize control. Most of them are small problems with nothing like the complexity of a modern app’s relationship to its surrounding ecology.
Classical designs don’t regard tests and testability as design criteria. Coming from a greenfield blank-page unoccupied building point of view, we can test it at the end as a whole thing and we’ll be fine.
Classical designs do attend to expression, tho not, perhaps, as much as a change-harvester would. That might be a "level of zoom" issue as much as anything else. Change-harvesters obsess over expression because it’s so dominant as a factor in cost-of-change.
When I say that change-harvesting designs are different, I don’t mean to throw out everything we learned from older ideas.
On the contrary, not only did those older designs often incorporate structural changeability and attend to expression, they also laid out many of the basic patterns — design parts? — we can use to get high changeability, now that we see that it’s so valuable.
Older design theories certainly know about how to isolate one thing from another safely, and they certainly know about how to shape a design around testability. And we can use all of that.
What prompted all this? A respondent, as so often. Please do talk to me about these things, folks. Your questions, qomments, qritiques, and QWAN not only give me juice to make content, they give me ideas about the shape of that content.
Someone described something that happened to him that has happened to me also, many times. Someone objected to incorporating code into our design for the sole purpose of enhancing our operational changeability.
The gist: tests and testability should not change design.
The idea that tests and testability are first-class participants in design is called the Steerability Premise. It is the single biggest change in software design theory since the turn of the century. It is still quite commonly resisted.
If you prefer the architectural metaphor: we can’t make people move out and move in again as we change the architecture. We have to make every change so that we get "same or better" experiences for those people. We need to know exactly what "same or better" means.
That means what we called "monitoring" above. We have to know the exact current state of our building or our creature before we change it, so we can change it in a way that is guaranteed to be same-or-better.
Even very modern design theory advocates, in my respondent’s case it was a big DDD fan — all serious developers should look into DDD and appreciate its ideas — and he was very troubled by the idea that the optimal design must include tests and testability.
Hopefully, I’ve given folks enough material here to formulate an answer when they’re challenged on this. If not, well, throw me some issues and I’ll take another swing.
The Steerability premise, that tests & testability are first-class design citizens, isn’t the only difference between old school design theory and change-harvesting design theory, but it is a major and obvious one.
A change-harvesters design imperative:
The best design is the design that most quickly puts an idea in direct contact with its market without sacrificing our ability to rapidly change that idea.
It enfolds classical design theory, but it extends, re-sorts and re-mixes it.
Supporting The PawCast
If you love the GeePaw Podcast, consider a monthly donation to help keep the content flowing. Support GeePaw Here.