After my oldest had been programming for a few years ze came to me and said, “I don’t understand why people talk about design and architecture like they are different. Isn’t it all just design?” I teared up a little and hugged hir. Yep, you understand.
Here’s how.
Containment is one of the basic mechanisms of thought. Inside this boundary I think about things differently than outside this boundary:
I treat the stuff inside my skin differently than I treat the stuff outside my skin
I treat people in my family differently than I treat people out of my family
I treat lines of code inside this function differently than I treat lines of code outside this function
Okay, that last one is a stretch, but it’s the ideal. When I’m changing this function, I want to be able to consider what’s inside it while ignoring what’s outside it. Being able to make this distinction gives me freedom to think that I wouldn’t have if I had to consider all lines of code in the whole system at the same time.
And so we use chunking as a tool to enable thought when we structure programs. Sometimes a behavioral change requires changing two functions. Fine. At least if the two functions are siblings then we don’t have to consider the whole system, we can just analyze the rest of the family and stop there.
Expressions in statements in functions in objects in modules in services in repositories.
As software designers we enable behavioral change by reducing the surface area (?)/ blast radius (?)/percentage of the system to consider (?) for the changes we want to make.
And then communicate those structural changes to our peers while they communicate their structural changes to us, but that’s a story for another day.
"When I’m changing this function, I want to be able to consider what’s inside it while ignoring what’s outside it. Being able to make this distinction gives me freedom to think that I wouldn’t have if I had to consider all lines of code in the whole system at the same time."
This has emerged for me as maybe The Key Point in software design practice. I want the option to ignore things. As many as possible. I want to focus with confidence. We humans, we can only function at all because we guess pretty well at what we can safely ignore. (Well enough to survive, anyway.) If we didn't need this ability, we would just dump everything in main() and be done with it.
And yet, so many programmers act like they don't need it. They are obsessed with the details. They feel most powerful when they know all the details.
I feel most powerful when I can ignore all the details.
I conjecture that the average competent programmer feels more comfortable with library-style abstraction than they do with framework-style/Template Method-style abstraction. They feel more open to trust the wisdom of recombinable small parts than to trusting the wisdom of reusable workflows. They feel more comfortable ignoring the details "above" them than they do ignoring the details "below" them in the dependency tree. I think there is much to be gained by helping them become more comfortable ignoring the details "below' them. In extracting Template Methods, workflows, frameworks, whatever they prefer to call them.
Anyone else?