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.