Layers
Domain, application, infrastructure, presentation, and the composition root. Three models meet at each boundary.
Five places. Each one answers a different question. The names below are the rings, not a required directory spelling. A feature-first tree nests the same rings under features/notes/. A hybrid tree keeps the inner three horizontal and slices presentation by feature. The questions do not change. Principles is why.
| Ring | Question |
|---|---|
| Domain | What are the concepts, and which rules always hold? |
| Application | What workflows does the system perform? |
| Infrastructure | How do we talk to the store and other processes? |
| Presentation | How does a client invoke a workflow? |
| Composition root | Which concrete adapter fulfills each port? |
What crosses a boundary
Three models describe the same note, and each one is allowed to look different.
wire payload command / result entity row
-------------- ---------------- ------ ---
{ title, body } -> SaveNote(title, body) -> Note(id, title, ...) -> notes(id, title, body, created_at)Presentation maps the wire payload to a command, and a result back to a wire response. The use case speaks only in commands, results, and domain types. Infrastructure maps the entity to a row and back. One request is that chain with the failures written in.
How a call moves
caller
-> presentation map wire to command, call the use case
-> application run the workflow
-> domain enforce the invariant, return the entity
-> infrastructure persist, through the port the use case already holds
-> presentation map the result or the failure back to the callerThe infrastructure call happens at runtime inside the use case, through a port. The source dependency still points inward: the use case imports the port, and the adapter imports the use case's world only by implementing the port. The composition root is what makes the two meet.