Clean Architecture

Clean Architecture is a way to structure software so that business rules stay independent of frameworks, databases, and UI details. The payoff is long-term maintainability: swapping a database, moving from REST to GraphQL, or redesigning the UI shouldn't force a rewrite of your core domain logic, because that logic never knew about those details in the first place.

The single idea that makes it work is the dependency rule: dependencies point inward, toward your business rules. Everything external — the web framework, the database driver, the API client — is a replaceable "detail" at the edges. You trade some extra structure for testability and flexibility.

TL;DR

Quick Example

A use case depends on an interface it owns; infrastructure implements it:

The Dependency Rule

Dependencies must point inward:

This is what prevents your domain from importing database drivers, HTTP frameworks, or UI code — and it's the whole game. Everything else is a consequence.

The Layers

From inner to outer (teams name these differently, but the direction is what matters):

  1. Entities / Domain — core business objects and invariants.
  2. Use Cases (Interactors) — application-specific rules; orchestrate entities and define input/output ports (interfaces).
  3. Interface Adapters — controllers, presenters, gateways; convert between HTTP/DB formats and domain types.
  4. Frameworks & Drivers — the web framework, database, external APIs, UI.

Wiring It Together

The HTTP adapter translates a request into a use-case call — the use case never knows HTTP exists:

Because the use case depends only on the PostRepository port: its tests need no HTTP or real database, the database can be swapped by changing one implementation, and REST or GraphQL can call the exact same use case.

Testing Strategy

Best Practices

Common Mistakes

Over-abstracting a small app

Business logic in the controller

FAQ

How is Clean Architecture different from a normal layered (MVC) app?

Traditional layered apps often let dependencies flow toward the database (the UI depends on services, which depend on the data layer). Clean Architecture inverts the outermost dependency: the database and framework depend on the application, via interfaces the application owns. That inversion is what keeps business rules pure and swappable — a standard MVC app usually has the domain coupled to the ORM.

Isn't all this indirection overkill?

It can be — for small apps or prototypes, the layers add ceremony without payoff. Clean Architecture earns its keep when the domain is genuinely complex, multiple interfaces exist (web + mobile + API), you expect framework or datastore changes, or the code needs to live for years. Match the investment to those signals rather than applying it reflexively.

Where does validation belong?

Domain/use-case validation (business rules — "a post must have a title," "a transfer can't overdraw") belongs in the inner layers, expressed in domain terms. Input-shape validation (is this JSON well-formed, are required fields present) can sit at the adapter boundary. Keep the business invariants in the core so every interface enforces them consistently.

How does it relate to Hexagonal Architecture / Ports & Adapters?

They're essentially the same idea with different vocabulary. Hexagonal Architecture's "ports and adapters" map directly onto Clean Architecture's interfaces (ports) and their implementations (adapters), and both enforce dependencies pointing toward the core. Onion Architecture is another close relative. Pick the terminology your team prefers; the dependency rule is identical.

Related Topics

References