Layered architecture and clean architecture: Ordering dependencies correctly
In short: A good architecture separates interface, business logic and data access and lets dependencies point only inwards so that business rules stay independent of frameworks and databases.
In more detail: As an application grows, HTML, database queries and business rules often mix in the same files. Changes become risky. Architecture patterns create order.
In Depth
Classic layers
- Presentation (UI, controllers, API endpoints).
- Application/business logic (services, rules, workflows).
- Data access (repositories, ORM, database). Requests go from top to bottom. Advantage: simple, widespread. Disadvantage: the business logic often depends on the database, and layers “leak” (SQL in the controller).
Clean/hexagonal/onion architecture
These approaches (Robert C. Martin, Alistair Cockburn) put the business logic in the middle and let dependencies point only inwards:
[UI / Web] [Database] [External APIs] <- details outside
\ | /
[Adapters / interfaces]
|
[Use cases]
|
[Entities / domain rules] <- core
The core defines interfaces (ports), for example OrderRepository; the database implementation (adapter) lies outside and is plugged in via dependency injection. This allows database, framework or UI to be exchanged, and the business logic is testable without infrastructure.
Typical building blocks
- Entity/domain model: business objects with rules (
Order). - Use case/service: one application case (“place order”).
- Repository: abstracts storage (
save,findById). - DTO (data transfer object): simple data structure for input/output at the boundaries.
- Controller/handler: translates HTTP into use-case calls.
- Mapper: converts between layers (entity ↔ DTO).
When is it worthwhile?
For long-lived, complex applications with many rules and several teams. For small projects or prototypes too much structure is over-engineering: start simple (for example a cleanly organised modular monolith), separate business logic from framework code and introduce abstractions only when needed. More important than the pattern are clear responsibilities and dependency direction.
See also: Hexagonal architecture, Modular monolith, Dependency injection, SOLID principles