Emergence
Good design doesn't have to be planned into existence up front. Kent Beck's four rules of simple design, as presented in Clean Code, describe a design that can emerge from a codebase as you keep applying a short checklist while you work. Follow the four rules in priority order and the rest of the SOLID toolbox - single responsibility, low coupling, clear naming - tends to show up as a side effect rather than something you had to force.
Rule 1: The system runs all the tests
A design is only "simple" if you can prove it still works, and a design without tests can't be proven at all. A system that passes a comprehensive suite of tests is verifiably correct in a way that a system you merely believe is correct is not - and pursuing testability has real design consequences. Chasing this rule pushes you toward smaller classes with a single purpose and toward depending on interfaces instead of concrete classes, because both of those make it dramatically easier to substitute a test double and verify one thing in isolation. In other words, the discipline of "make it testable" quietly drags your design toward SRP and DIP even if you never set out to apply either principle on purpose.
Rule 2: Contains no duplication
Duplication is the enemy once you have a passing suite of tests to protect, because every duplicated fragment is one more place a bug can hide and one more place a fix has to be made correctly. This isn't just about literal copy-pasted lines - two classes that solve the same underlying problem with slightly different code are duplicating a decision, not just text, and that's more expensive to maintain than duplicated syntax.
Removing duplication is also what pulls small, reusable methods out of a bigger class,
which shrinks the class's footprint and starts to reveal the abstractions that were hiding
inside the repeated blocks. A TEMPLATE METHOD pattern - a base class defining an
algorithm's shape and letting subclasses fill in one varying step - often falls out of this
exact process: notice that several methods repeat the same skeleton with one different step,
and extract that skeleton once.
Rule 3: Expresses the intent of the programmer
Code that works and is duplication-free can still be nearly unreadable, and unreadable code
costs the next person (often you, in six months) far more time than it saved the person
who wrote it quickly. Expressive code leans on the same tools this course has already
covered: names that say what a thing is for, functions small enough to do one
understandable job, and classes and methods organized the way Meaningful Names
and the functions chapter both describe. Reaching for standard vocabulary is another lever -
naming a class OrderVisitor or PaymentCommand tells anyone who recognizes the Visitor
or Command pattern exactly what role it plays, without a trip into the implementation. A
well-named test suite is itself a form of documentation - reading the tests should tell a
new contributor how the system is meant to be used, without them having to trace through
the implementation first.
Rule 4: Minimizes the number of classes and methods
The first three rules can be over-applied. Taken to an extreme, "no duplication" and "single responsibility" can spawn a swarm of tiny classes and interfaces for every conceivable point of variation, most of which never actually vary. This rule is the counterweight: keep the class and method count as low as it can be while still satisfying the other three rules first. If a single class with a couple of methods expresses the intent just as clearly as five tiny classes would, the single class wins - not because fewer files is a goal in itself, but because every extra class or interface is one more thing a reader has to hold in their head before they understand the system. A coding standard that insists on an interface for every class, or that fields and behavior must always live in separate data and behavior classes, is the kind of dogma this rule pushes back on - a split made on principle, not because the current class count is actually a problem.
Why the order matters
The order is deliberate: tests come first because nothing else is safe to change without them, duplication and intent come next since a tested codebase can be reshaped freely, and minimizing classes comes last, as a brake on the other three rather than a goal of its own. Applied together, in small steps, repeated constantly, these four rules are enough to let a clean design emerge from a working system - no big upfront architecture required.