Clean Code Design
Clean Code rules for boundaries, object/data design, systems, and emergence
Tags
Overview
Purpose
Clean Code rules for boundaries, object/data design, systems, and emergence
Rules
BO-001: Wrap third-party interfaces in your own classes to limit exposure
Isolation prevents vendor lock-in and limits blast radius of API changes
BO-002: Write tests to explore and verify understanding of third-party APIs
Learning tests validate your assumptions about external behavior
BO-003: Learning tests are free, positive ROI — verify new releases don't break your usage
Catch breaking changes early with existing test investment
BO-004: Define your own interface for what you need; implement adapter when real code exists
Program against your needs, not someone else's API surface
BO-005: Minimize points of contact with third-party code; keep it isolated
Every touchpoint is a coupling risk
OADS-001: Express data in abstract terms, not concrete implementation details
Abstraction hides implementation, enabling change without ripple effects
OADS-002: Objects hide data behind abstractions and expose behavior; data structures expose data and have no behavior
The fundamental dichotomy — mixing creates hybrids that are hard to extend
OADS-003: Law of Demeter: a method f of class C should only call methods of C, objects created/passed to f, or instance variables
Reaching through objects creates deep coupling chains
OADS-004: Chains of method calls (train wrecks) should be split up or redesigned
a.getB().getC().doSomething() violates Demeter and creates fragile code
OADS-005: Don't create classes with behavior AND public variables that expose internals
Hybrids get the worst of both worlds — hard to add functions AND data
OADS-006: DTOs (data structures with public variables and no functions) are useful for boundary communication
Database rows and socket messages are data, not objects
OADS-007: Active Records with save/find methods — treat as data structures, put business rules in separate objects
Active Records that accumulate business logic become god classes
SY-001: Don't over-engineer; use simple solutions until complexity requires more
YAGNI — premature abstraction is the root of unnecessary complexity
SY-002: DSLs can raise abstraction level and communicate intent more clearly
Domain-specific languages bridge the gap between code and requirements
SY-003: Delay architectural decisions to last responsible moment for maximum information
Early decisions are made with minimum information
SY-004: Use tests to drive architecture evolution; refactor as needed
Tests provide safety net for architectural change
EM-001: Testing leads to better design through the need for testability
Testable code is loosely coupled by necessity
EM-002: Tight coupling makes it hard to write tests
Testing difficulty is a design smell signal
EM-003: Following SRP, DIP, and using DI leads to testable systems
SOLID principles naturally produce testable code
EM-004: Tests give confidence to refactor — cleaning code after getting it to work
Red-Green-Refactor: make it work, then make it right
EM-005: Duplication manifests in identical code, similar implementations, or similar algorithms
DRY applies at all levels of abstraction
EM-006: Template Method pattern can eliminate higher-level duplication
Algorithmic duplication needs structural solutions
EM-007: Take pride in workmanship — care about your code
Craftsmanship is a choice, not a talent
EM-008: Try (multiple times) to express yourself clearly
First draft code is rarely the clearest expression
EM-009: Balance minimizing class/method count with the other three rules
The four rules of simple design in priority order