Design principles
Universal ideas that most of the patterns in this catalog are just careful applications of.
SOLID gets the acronym and the interview questions, but a handful of older, blunter principles do most of the actual work. Every creational pattern is "encapsulate what varies" with a specific answer for what varies. Almost every structural and behavioral pattern is "program to an interface" plus a shape. Learn these ten and the pattern catalog stops looking like twenty-three unrelated tricks and starts looking like the same three or four moves, applied over and over to different shapes of problem.
Ten pages, each standing alone with its own worked example, its own failure mode when over-applied, and its own quiz - but they were never really ten separate ideas. DRY, KISS and YAGNI are the index-card rules that catch most damage before it starts. Encapsulate What Varies and Separation of Concerns are two grain sizes of the same "wall off what changes" instinct. Coupling and Cohesion is the measurement those two produce. Program to an Interface and Dependency Injection (a full pattern of its own, in the additional-patterns section) are how you act on that measurement. Law of Demeter is coupling caught in one specific, grep-able shape. And Favor Composition over Inheritance plus the Composing Objects Principle are the same "assemble from small collaborators" idea, at two different scales.
What good design buys you
Two things, and they are both about the future rather than today.
Code reuse
Cost and time are the two metrics that decide whether a product ships. Reuse is the obvious lever: stop writing the same thing over and over. The obviousness is a trap, though - making existing code work in a new context usually costs more than expected, and the reason is always the same. Tight coupling, dependencies on concrete classes rather than interfaces, hardcoded operations. The logic was reusable; its wiring was not.
Erich Gamma, one of the four authors of the original pattern catalog, describes reuse as three levels, and patterns sit deliberately in the middle:
A framework distills your design decisions for you - it identifies the key abstractions, names them, and calls your code when it is ready ("don't call us, we'll call you"). That is enormous leverage and an enormous bet. Patterns give you the design idea without the commitment to somebody else's concrete code.
Extensibility
Change is the only constant in this job. You shipped for Windows and now they want macOS. You built a GUI framework with square buttons and round buttons became fashionable. You designed a clean e-commerce architecture and a month later somebody wants to take orders over the phone.
Three reasons this always happens:
- You understand the problem better once you have solved it. By the time version one is done you are ready to rewrite it, because now you know what it should have been.
- The ground moves. Something outside your control changes - a browser drops Flash, a vendor deprecates an API - and your plans go with it.
- The goalposts move. The client loved version one so much that they now see eleven more things it could do. These are not frivolous requests; your good first version caused them.
The bright side: if someone asks you to change your app, someone still cares about your app. That is why experienced developers design for change they cannot yet name - which is exactly what the ten principles below are tools for doing without over-designing for change that will never come.
The ten principles
The first three fit on an index card and prevent most of the damage. The rest are the ones the pattern catalogue is built out of.
- DRY - one authoritative home per piece of knowledge, and why merging code that merely looks alike is worse than repeating it.
- KISS - fewer moving parts to hold in your head, which is not the same thing as fewer characters.
- YAGNI - build for the requirement in front of you, not the one you can imagine.
- Law of Demeter - talk to your immediate collaborators, not to the objects they happen to return.
- Separation of concerns - one job per part, with no overlap. SRP is this principle applied to a single class.
- Coupling and cohesion - the two dials every other principle here is really adjusting: low coupling, high cohesion.
- Encapsulate what varies - find the part that changes and put a wall around it. Every creational pattern is this move.
- Program to an interface - depend on the category, not the concrete thing. Most structural and behavioral patterns are this plus a shape.
- Favor composition over inheritance - why a second dimension of variation is the moment a hierarchy stops paying for itself.
- Composing objects - assemble behavior from small collaborators instead of one object that does everything itself.