Clean Code Chapter 11: Systems
Principles
At system scale, cleanliness is about separation of concerns: how the whole is constructed, wired, and allowed to evolve without tribal knowledge.
Construction vs use
Building the object graph is a different concern from running business logic. A composition root (main, DI container, factory module) wires dependencies; application services then use abstractions without new-ing infrastructure mid-flow.
Dependency injection
Inject collaborators so modules depend on interfaces they need, not on concrete construction details. That keeps startup wiring explicit and units testable.
Cross-cutting concerns
Logging, transactions, security, and similar concerns need clear mechanisms (decorators, aspects, middleware), not copy-paste through every use case.
The city metaphor
Martin compares building software to building a city: different people specialize (utilities, roads, buildings), and the whole stays livable through clear boundaries. Your “city planning” is architecture and wiring; your “buildings” are modules that do not each dig their own water main.
Aspects and cross-cutting concerns
When the same logging, transaction, or security step wraps many use cases, an aspect, decorator, or middleware keeps that policy in one place instead of copy-paste.
Growth without folklore
A clean system stays navigable as it scales. Optimize for clarity and testability first; premature infrastructure platforms are still premature. Test-drive architecture the same way you test-drive modules: small proofs, then expand.
flowchart TD
Main[Composition root] --> Wire[Wire dependencies]
Wire --> App[Application services]
App --> Domain[Domain logic]
App --> Adapters[IO adapters]
Snippet
Examples below are in Java.
Construction mixed into use:
public class OrderService {
public void place(Order order) {
Repository repo = new JdbcRepository(DriverManager.getConnection(url));
repo.save(order);
new SmtpNotifier().send(order.email());
}
}
Injected collaborators:
public class OrderService {
private final OrderRepository repository;
private final Notifier notifier;
public OrderService(OrderRepository repository, Notifier notifier) {
this.repository = repository;
this.notifier = notifier;
}
public void place(Order order) {
repository.save(order);
notifier.send(order.email());
}
}
So what
Build the object graph in one place. Inject collaborators. A system is clean when a new person can find their way without folklore.