Changeability Is the Goal
Design has no intrinsic virtue. Every structural claim in this domain has to cash out as a change that got cheaper, or it is decoration.
The requirement, the obvious build, and why it breaks
Every lesson starts where the work starts: someone asked for something, and the first implementation that comes to mind survives until the requirement changes.
How do I tell a good design argument from an aesthetic preference?
A code review comment says "this should use the repository pattern". The author asks why. The reviewer says it is cleaner.
Follow established principles. SOLID, clean architecture and the patterns exist because they work; disagreeing with them is inexperience.
Principles are compressed advice for situations. Applied outside the situation that produced them they are frequently wrong, and appealing to authority hides that.
- Principles are compressed advice for situations. Applied outside the situation that produced them they are frequently wrong, and appealing to authority hides that.
- "Cleaner" is not a shared standard. Two engineers can hold opposite structural preferences and both cite the same principles honestly.
- It also makes disagreement unresolvable, so it gets settled by seniority — which is how codebases acquire structure nobody can defend and nobody may question (Tone, Disagreement and Receiving Review).
- And it is empirically shaky. Many of the strongest claims in this field have never been demonstrated to reduce anything measurable (How SOLID Gets Misused).
What limits the solution, and what must never stop being true
This domain leads with these two. A design that ignores its constraints is not a design, and an invariant nobody named is one nothing is protecting.
- Both people are acting in good faith and neither has a shared standard to appeal to.
- The change is small; the discussion is about to cost more than the code.
- A design claim must be falsifiable. If no possible observation would change it, it is a preference and should be labelled as one.
Who owns what, and where the seams fall
Responsibilities decide boundaries; boundaries decide what an interface has to say.
- Whoever proposes a structure owns naming the change it makes cheaper.
- Whoever resists owns naming what it costs. Both are falsifiable claims and both can be wrong.
- The line between design argument and preference is exactly whether a specific future change is named. Everything else follows from that.
Two versions of the same review comment
The difference is not politeness or seniority. One version can be answered with evidence and the other can only be agreed or resented.
"This should use the repository pattern — it's cleaner and follows separation of concerns." The author can: - agree (and learn nothing) - disagree (and it becomes about them) Nothing would settle it either way.
"Three services now build this same tenant-scoping clause inline. If we get scoping wrong in one, it's a data leak across tenants. A repository puts that clause in one place and lets us test it once. Cost: an indirection, and it will leak the moment we need a query with a join. Worth it for the scoping; I wouldn't add it for a single caller." The author can now answer: - "there's only one caller, the other two are different" - "scoping is already enforced by a policy in the driver" - "agreed, and let's keep the join escape hatch"
The second names the invariant at risk (tenant isolation), the specific change it makes cheap (scoping in one place), and its own cost (leaks on joins). All three are things the author can accept or refute with facts about this codebase, which means the discussion can actually end.
The question that terminates the argument
One question does most of the work, and it is worth asking of your own proposals before anyone else has to: what change does this make cheaper, and how would I know if I were wrong?
Three answers are legitimate and only one of them is a design argument. Being clear which one you are making is most of the value.
- The second option is the strongest and the most under-used: present evidence beats predicted futures every time.
- The third is where this standard is weakest, and the honest response is to admit that rather than force it into the first category.
- A proposal that cannot be placed in any of these five is usually pattern-matching on a book (Pattern Overuse).
What would make this proposal wrong?
when "So we can add a second provider without touching checkout."
cost A design argument. Refutable by showing the change will not come, or that it is cheap without the structure. Argue it on the merits.
when "This rule is in four places and one of them is already wrong."
cost The strongest kind — evidence, not prediction. Should usually win.
when "I could not follow this without asking you."
cost Legitimate and hard to measure. Treat the reviewer's confusion as the evidence it is, rather than requiring them to prove it.
when "The other six modules do it this way."
cost Honest and often sufficient. Say it plainly rather than dressing it as a principle — and notice when it means propagating something you would not choose again.
when "This is cleaner."
cost Not a design argument. Fine as a preference, and it should not outrank the author's judgement on its own. If it is about formatting, a tool should be settling it (What to Automate Out of Review).
How to build it
Most important first.
- State the change. "This should be a repository so we can swap Postgres for DynamoDB" is arguable; "this is cleaner" is not.
- Ask whether that change is plausible. If nobody expects to swap the database, the argument has been made and lost, honestly (The Cost of Change).
- Name what it costs — indirection, a leaky abstraction over transactions, a boundary that will not survive contact with a query that needs a join (When the Repository Is Just Indirection in Backend).
- Accept preference as preference. Consistency is a legitimate reason; "we do it this way here" is honest in a way that "cleaner" is not.
- Let tooling settle the aesthetics so review can spend its attention on the parts that are actually arguable (What to Automate Out of Review).
What the next change costs
The field this whole domain exists for. A structure is only better if it makes the change after this one cheaper — and it is worth saying which changes it does not help.
- The standard itself costs a sentence per design discussion. It saves the recurring, unresolvable argument, which in most teams is a substantial share of review time.
- It also changes what gets built: structures that cannot name their change tend not to get built, which is the intended effect.
- Demanding falsifiability slows down experienced engineers whose instincts are usually right, and some of that friction is genuinely wasted.
- Not every good structure has a nameable change. Some are about comprehensibility, which is real and much harder to argue about — and this standard is weakest exactly there.
What can go wrong
- The standard becomes a weapon — demanding a named change for every suggestion turns review into an interrogation and is its own kind of unpleasant.
- Falsifiability is used selectively, applied to other people's proposals and not one's own.
- It collapses into "never change anything without a ticket", which is the opposite failure and just as expensive.
- This lesson depends on being able to price a change, which is why it comes after
cost-of-changerather than opening the domain.
- "So principles are useless." They are compressed experience and often right. The point is that they are evidence in an argument, not the conclusion of one.
- "So only measurable things matter." Comprehensibility matters enormously and resists measurement. The demand is for a *named* consequence, not a metric.
- "This means juniors can veto senior design." It means both have to make an argument. That is usually good for the design and always good for the team.
Testing it, and how it ages
- The strongest version of a design argument is a test that would be easy under the proposal and is hard now. If nobody can write that test, the claim is weaker than it sounded (Testing as Design Feedback).
- A named change also gives the structure an expiry: when it becomes clear the change will never arrive, the structure can be removed with the same argument that justified it (Revisit Triggers).
- This is how a codebase sheds structure, which almost none of them do, because nothing ever gives permission.
Where this applies
This domain's advice is contested more than most. These labels say what each claim is specific to — and where CONTESTED appears, the note gives the strongest form of the opposing view rather than a caricature.
- GENERALRequiring a design claim to name a consequence is a standard of argument, so it applies wherever design is discussed, independent of stack.
- CONTESTEDThe strongest opposing view: much of what makes a codebase good is taste that cannot be decomposed into named future changes, and demanding justification for each move privileges the articulate over the skilled while slowly eroding standards nobody can defend on the spot. That is a real cost, and it is why "consistency with the surrounding code" should be accepted as a complete answer.
Where the depth lives
This domain teaches the codebase-level structure and hands the rest off.
- — Testing & Reliability Engineering — "what test would this make easy" is often the sharpest form of a design argument, because it turns a structural claim into something you can write down and run.