Layered application
Where responsibility and transactions belong
- UI: HTTP, Console, or message handler
- Application: use case and transaction boundary
- Domain: rules, entities, and value objects
- Infrastructure: database, queue, and framework
Way of working
I do not choose architecture by the name of a pattern, but by the complexity of the problem. The goal is clear boundaries, safe changes, and a solution proportionate to the application.
In larger applications developed over the long term, I separate UI, Application, Domain, and Infrastructure. Domain rules are then not attached to a framework, database, or a particular API, and each part has clearer responsibility.
That does not mean every part of an application needs full Clean or hexagonal architecture. For a simple problem with a few inputs and no complex rules, a direct service-based solution is often clearer and less costly to maintain.
Not familiar with a term? Read a concise explanation in the glossary.
How my approach evolved
Earlier
More complex system parts
Today
A pragmatic choice
Boundaries and dependencies
Layers are not an end in themselves. They show how dependencies may flow: UI calls an application use case, the use case uses the domain, and technical details implement the interfaces the application needs.
I adjust the approach according to the risk of change, application lifetime, number of integrations, and the team’s ability to maintain the architecture in practice.
Layered application
Port and adapter
Public example
Principles I use
I can help assess where architecture brings real value and where it is better to keep a simple, readable solution.