Clean Architecture Layers and the Dependency Rule
Fast recall
Quick revision
Core answer
The four layers and what belongs in each, the strict inward-only dependency rule, and the dependency-inversion mechanic that lets inner circles trigger outer ones without depending on them.
Putting framework annotations in entities or use cases, or letting use cases import from interface adapters.
Discuss when the four-circle model is overkill (small CRUD), pragmatic packaging (3 packages instead of 4 layers), and how it relates to Hexagonal/Onion.
Interview-ready guide
Interview answer
The four circles
Innermost to outermost: Entities, Use Cases, Interface Adapters, Frameworks & Drivers.
Entities: enterprise-wide business rules and invariants. Plain objects, no framework. Survive any app — a Money value object or BankAccount aggregate same in any of the company's apps.
Use Cases: application-specific business rules. Orchestration of entities for this app's user goals. One class per user goal: PlaceOrder, RefundOrder. Depends on abstract interfaces (OrderRepository) defined here, implemented outside.
Interface Adapters: controllers (translate HTTP → use case input), presenters (use case output → HTTP response), gateways (implement repository/external API interfaces). DTOs and JPA entities live here.
Frameworks & Drivers: Spring, JPA, web framework, DB driver. Glue and configuration. Most volatile, easiest to swap.
The Dependency Rule
Source code dependencies must point only inward.
- Use Cases can import Entities. Entities cannot import Use Cases.
- Interface Adapters can import Use Cases. Use Cases cannot import Interface Adapters.
- Frameworks know about everything inward; nothing inward knows about frameworks.
No Spring annotations on Entities or Use Cases. No JPA @Entity on domain objects.
Why: inner circles are stable; shouldn't change because Postgres → Mongo. Inner-to-outer dependency would break this stability.
Crossing boundaries outward — dependency inversion
Use cases must call DB but can't import it. Solved by inversion: define interface in the inner layer, implement in the outer layer.
OrderRepository owned by use cases. PlaceOrderUseCase depends on it. JpaOrderGateway in adapter layer implements it.
Dependency arrow: adapter → use case (inward). Runtime data flow: use case → adapter via interface. Spring @Configuration wires the implementation at startup.
Crossing inward
OrderController in interface adapters: knows Spring + use cases. Calls placeOrder.place() with plain Java args (no HttpServletRequest). Use case returns domain object; presenter (OrderResponse.from) converts to HTTP shape. Use case has no idea HTTP exists.
Pragmatic packaging
Three practical packages: domain (entities + value objects), application (use cases + ports), adapter (in/web for controllers, out/persistence for JPA, out/payment for Stripe). Plus config for Spring @Configuration.
Maps cleanly to the four formal layers. ArchUnit enforces dependency rule in CI.
Clean vs Hexagonal vs Onion
Same family. Hexagonal (Cockburn 2005) ports & adapters terminology. Onion (Palermo 2008) concentric circles. Clean (Martin 2012) four named circles, explicit Use Case layer.
Same dependency rule, same interface inversion, same domain-at-center. Pick vocabulary your team prefers; consistency matters more than label.
Common mistakes
- @Service, @Transactional in inner circles — belongs outside
- JPA @Entity on domain objects — map in persistence adapter
- Use cases imported by entities — backwards
- One use case = one endpoint dogma — user goals can have multiple endpoints (REST + admin + CLI)
- Returning domain objects from controllers — use presenters/DTOs
- Clean as gospel for tiny services — 4-endpoint CRUD is fine layered
Recommendation
Apply Clean Architecture for non-trivial Spring Boot services with rich domain logic, multiple input adapters (HTTP + Kafka + scheduled), or strict testability needs. Use the pragmatic three-package structure (domain / application / adapter); don't over-engineer with four formal layers in small services. Keep entities and use cases free of Spring/JPA annotations — wire dependencies in @Configuration. Enforce the dependency rule with ArchUnit in CI. For simple CRUD, stick with classic layered — Clean's complexity isn't free.
Clean Architecture Layers and the Dependency Rule
Direct Answer
Clean Architecture (Robert C. Martin, 2012) organizes code as four concentric circles — from the inside out: Entities (enterprise business rules), Use Cases (application business rules), Interface Adapters (controllers, presenters, gateways), and Frameworks & Drivers (Spring, JPA, web, DB). The Dependency Rule states: source code dependencies must point only inward. Inner circles know nothing about outer circles. Cross the boundary inward via interfaces; cross outward via dependency inversion. Result: domain logic is testable, framework-free, and survives infrastructure changes.
Common Mistakes & Pitfalls
Putting framework annotations in entities or use cases, or letting use cases import from interface adapters.
Check your understanding
Answer these without looking back at the article.
- Show how dependency inversion lets a use case call the database without importing it.
- How do you enforce the dependency rule in CI?
- Where does @Transactional live in a Clean Architecture Spring Boot app?
- When is Clean Architecture overkill?
Related interview prep categories
1Want a guided curriculum order?
These modules are also sequenced in our flagship backend interview track — open it when you prefer an ordered path instead of browsing by topic.