Clean Architecture draws four concentric rings - Entities, Use Cases, Interface Adapters, and Frameworks & Drivers. For a typical web application, what kind of code lives in each of these four rings, and how does data get from an outer ring's format into a form the innermost ring can use?
answer
- Entities = enterprise rules
- Use Cases = app-specific orchestration
- Interface Adapters = controllers+presenters+gateways
- Frameworks/Drivers = the actual tech
- data crosses as plain DTOs, not framework types
basics
~20 sEntities hold core business rules; Use Cases run application-specific workflows; Interface Adapters translate between the app and the outside world (controllers, presenters); Frameworks/Drivers are the actual web server, DB, UI. Data crosses rings as plain data structures, converted at each boundary.
solid answer
~50 sEntities are the innermost ring - plain objects encoding enterprise-wide business rules that would hold true regardless of what application uses them (e.g. an Order entity's invariant that total must equal the sum of line items). Use Cases wrap entities with application-specific orchestration - the steps for 'place order' or 'cancel subscription' - and define input/output boundary interfaces. Interface Adapters convert data between the use case's shape and the outside world's shape: Controllers translate incoming HTTP/CLI/gRPC requests into use-case input models, and Presenters translate use-case output models into view models or JSON. Frameworks & Drivers is the outermost ring: Spring, the actual database, the web server, UI frameworks - all the volatile, replaceable machinery. Data crosses each boundary as simple DTOs or plain data structures, never as framework-specific types (no ORM entities, no HTTP request objects) reaching past Interface Adapters into Use Cases, which keeps every inner ring compilable and testable without any outer-ring dependency present.
go deeper
Can name the four rings in order and give one example of what lives in each.
Can explain how a request's data physically changes shape as it crosses each boundary (HTTP request -> input DTO -> use case -> output DTO -> view model -> JSON).
Can identify misplaced code (business logic in a controller, framework leakage in a use case) in a real codebase and explain the fix.
Can decide, for a specific system, which use cases genuinely need the full adapter/presenter split versus which can safely take a shortcut.
## Entities: the innermost ring Entities are the innermost ring in Clean Architecture and hold the enterprise-wide business rules and critical data structures - the objects and invariants that would still make sense even if this particular application didn't exist, because they encode truths about the business domain itself. - An `Order` entity enforcing 'total must equal the sum of line items' or an `Account` entity enforcing 'balance cannot go negative without an overdraft flag' belongs here. - Entities have no knowledge of use cases, HTTP, databases, or UI; they are typically the most stable code in the system because they change only when the fundamental business rules change, not when technology choices change. ## Use Cases: application-specific orchestration One ring out sit Use Cases (Interactors), which encode application-specific business rules - the orchestration steps needed to accomplish one particular thing a user or system does, such as 'place an order' or 'cancel a subscription.' A use case pulls in one or more entities, applies whatever validation and sequencing the specific operation requires, and talks to the outside world exclusively through interfaces it declares itself: - an **output boundary** (sometimes literally an `OutputBoundary` interface or a presenter callback); - any **gateway interfaces** it needs, like `OrderRepository` or `PaymentGateway`. Critically, use cases never import a concrete database class, a concrete HTTP framework class, or a concrete UI class - only interfaces they own. ## Interface Adapters: translation in both directions The Interface Adapters ring is where the translation happens in both directions. - **Going in.** A Controller takes a framework-specific input - an HTTP request, a CLI argument array, a gRPC message - and converts it into a plain input data structure the use case's `execute()` method understands, containing nothing but primitive/simple types, never framework classes. - **Going the other way.** When a use case finishes, it hands a plain output data structure to its output boundary, and a Presenter (also in this ring) converts that into a view model shaped for whatever the delivery mechanism needs - a JSON DTO for a REST API, a printable string for a CLI, a `ViewModel` object for a UI template. This ring also holds Gateway implementations - the concrete class that implements `OrderRepository` using JPA, for instance - even though the gateway's interface was declared one ring further in. ## Why the translation code gets its own ring The reason for splitting Interface Adapters into its own ring, distinct from both Use Cases and Frameworks/Drivers, is to give the translation code somewhere to live that is neither pure business logic nor raw framework machinery. Without this ring, teams end up doing input parsing and JSON marshalling directly inside use-case methods (polluting business logic with HTTP concerns) or, worse, letting entities themselves grow Jackson annotations and getters/setters shaped for a particular API response (polluting the domain model with a specific client's needs). Concentrating conversion logic in Controllers/Presenters/Gateways means a change to the wire format - renaming a JSON field for a specific mobile client - touches only the Presenter, never the use case or entity. ## The cost, and where it goes wrong The cost of this many rings is real: a single 'place order' flow can require an input DTO, an output DTO, a use-case interface, a use-case implementation, a controller, a presenter, and a gateway implementation - seven-plus files for one operation, legitimately heavy for a small app. 1. The most common failure mode in production codebases is skipping the translation and passing Entities straight out of a controller as the HTTP response body; it looks harmless until the entity gains a method or a lazy-loaded JPA relationship that then gets serialized straight to a client, causing either an accidental data leak or a `LazyInitializationException` in production. 2. A second common failure is a 'fat' presenter or controller that starts making its own business decisions (e.g., deciding whether a discount applies) because it's easier than adding a parameter to the use case - quietly moving business logic into a ring that isn't supposed to hold it. ## One request, end to end Concretely, in an order-processing service: an HTTP POST /orders hits `OrderController`, which builds a `PlaceOrderInputData(customerId, items)` and calls `PlaceOrderUseCase.execute(input)`. That use case loads/validates the `Order` entity, calls the `PaymentGateway` interface it owns, and on success builds a `PlaceOrderOutputData(orderId, status)` which it hands to an `OrderPresenter`. The presenter converts that into `OrderResponseJson(id, status, links)` that Spring serializes back to the client. Not one of those inner classes imports Spring, JSON, or JPA - only the Controller, Presenter, and the Gateway implementation know those exist.
- Where does validation of a raw HTTP request - like checking a required field is present - belong: the controller or the use case?Structural/format validation (is this field present, is it the right type) typically belongs in the controller or input DTO construction, since it's about the shape of the incoming request. Business validation (is this discount code still valid, does this customer have enough credit) belongs in the use case, since it requires domain knowledge the controller shouldn't have.
- If a mobile client needs a slightly different JSON shape than a web client for the same use case, where does that difference get handled?In the Presenter - you can have multiple presenters implementing the same use case's output boundary, one per client shape, without touching the use case or its output data type at all. This is exactly the kind of change the Interface Adapters ring exists to absorb.
- What goes wrong if a Gateway implementation (say, JpaOrderRepository) is placed in the same package as the Use Cases instead of Interface Adapters/Frameworks?The use-case package would end up importing JPA classes to compile the gateway implementation, giving the whole package a hard dependency on Hibernate even though most of its classes have nothing to do with persistence - undermining the ability to test or reuse that package without a database present.
Like an embassy: the ambassador (use case) never speaks directly in the host country's dialect or paperwork format - a translator/liaison staff (interface adapters) converts every incoming request and outgoing statement, so the ambassador's actual instructions from home (entities/business rules) never have to change just because the host country changes its forms.
saying these in an interview costs you the question
- can't distinguish what belongs in Entities versus Use Cases
- has the controller call the database directly, skipping the use case entirely
- lets a use case return an ORM entity straight to the presenter/controller unmodified
- puts business validation logic inside the controller
- can't explain what a presenter does differently from a controller