Application
The application runs the use cases: one handler per request, which calls the domain and makes the change atomic and reliable. It lives in application/; the adapters of its contracts live in driven/.
Why
A controller that loads an order, checks it, saves it and sends an email mixes HTTP, rules and storage. A second entry point, a consumer or a CLI, copies it. If the email leaves before the save fails, the customer is told about an order that does not exist.
The fix
Each use case is one handler that only coordinates: load, call the domain, save, hand over the events. The save and the events commit together, and the events are sent after.
How a request flows
2AnnounceAn event translator turns domain events into integration events, stored in the outbox with the change.
The building blocks
| Building block | What it is | Use it when |
|---|---|---|
| Command handlers | The application service of one use case that changes the system. | A request changes state: create, place, cancel. |
| Query handlers | The application service of one read. | A request only reads. |
| Event translators | Turns domain events into integration events. | Other contexts must hear about a change. |
| Integration events | What other contexts receive when something happens: JSON. | You define what leaves your context. |
| Event publishers | Sends integration events to the rest of the system. | You plug in a broker, or deliver in process. |
| Unit of Work | Makes a use case atomic: commit on success, roll back otherwise. | A use case writes more than once, or writes and records events. |
| Outbox | Stores integration events with the change, then relays them, so none is lost. | Events must not be lost nor sent for a change that failed. |
See also
- Domain, what the handlers call
- Strategic, how contexts meet
- Rules:
layers/no-outward-import,tactical/no-mixed-handler