Hexagonal Architecture: Ports and Adapters
Objectives
By the end of the lesson, you can explain what hexagonal architecture solves, name the roles of the port and the adapter, and distinguish it from the layered structure.
Why is it needed?
In a layered structure the business logic is often tied to the database or the presentation, because the dependency points downward. That is why it is hard to test the logic without the real database, and hard to replace the external technology. Hexagonal architecture reverses this dependency.
What is it?
According to Alistair Cockburn's description, the goal is that the application can be driven equally by a user, another program, an automated test or a batch script, and can be developed and tested without real devices and databases.
- A port is a purposeful conversation: an interface defined from the application's point of view, which states with what purpose and in what form it communicates with the outside world.
- An adapter is a technology-specific connector that translates a concrete external technology (user interface, test, database) towards the port and back.
- Cockburn distinguishes primary actors (that drive the application) and secondary actors (driven by the application); he also calls the corresponding adapters driving and driven adapters.
flowchart LR
UI["Interface adapter"] --> P1["Inbound port"]
T["Test adapter"] --> P1
subgraph Core["Application and business logic"]
P1 --> L["Business rules"]
L --> P2["Outbound port"]
end
P2 --> DBA["Database adapter"]
P2 --> EXT["External service adapter"]
The business logic knows the ports, not the technology. Adapters are replaceable: the same port can be connected to a real database and to a substitute used in tests.
How does it relate to the layered structure and the others?
In the layered structure the direction of dependency points from top to bottom; in the hexagonal one the dependency points inward: the adapters depend on the ports, the core does not depend on the adapter. The hexagonal structure does not split into services: it lives in the same deployment unit, and the module of a modular monolith can also have such an internal structure (2.4). The "onion" and "clean" architectures, which work on a similar principle, are often mentioned too; they handle the direction of the internal dependency similarly, but the course does not discuss them separately.
By aspect
| Aspect |
Hexagonal structure |
| Coupling |
The core is not bound to technology; there is a contract between adapter and port |
| Testability |
Good, because the outside world can be replaced |
| Deployability |
Unchanged: the structure can still be one unit |
| Cost |
More interfaces and connectors; may be superfluous in a smaller application |
Common misconceptions
| Statement |
Clarification |
| "The six sides of the hexagon mean six ports." |
According to Cockburn, the hexagon is a hexagon only to leave room for drawing in ports and adapters; the number of ports is usually small (2–4). |
| "Hexagonal architecture splits into services." |
It is an internal structure; it works in one deployment unit too. |
| "The adapter contains the business rule." |
The adapter only translates; the rule is in the core. |
In short
- A port is a conversation defined from the application's point of view, an adapter fits it to a concrete technology.
- The dependency points toward the core, so the outside world is replaceable and substitutable.
- Hexagonal structure is an internal structure, not a split.
Review questions
- What is the difference between a port and an adapter?
- How does the direction of dependencies differ from the layered structure?
- When is introducing a port unnecessary?
Learning resources
Hexagonal Architecture: Ports and Adapters
Objectives
By the end of the lesson, you can explain what hexagonal architecture solves, name the roles of the port and the adapter, and distinguish it from the layered structure.
Why is it needed?
In a layered structure the business logic is often tied to the database or the presentation, because the dependency points downward. That is why it is hard to test the logic without the real database, and hard to replace the external technology. Hexagonal architecture reverses this dependency.
What is it?
According to Alistair Cockburn's description, the goal is that the application can be driven equally by a user, another program, an automated test or a batch script, and can be developed and tested without real devices and databases.
flowchart LR UI["Interface adapter"] --> P1["Inbound port"] T["Test adapter"] --> P1 subgraph Core["Application and business logic"] P1 --> L["Business rules"] L --> P2["Outbound port"] end P2 --> DBA["Database adapter"] P2 --> EXT["External service adapter"]The business logic knows the ports, not the technology. Adapters are replaceable: the same port can be connected to a real database and to a substitute used in tests.
How does it relate to the layered structure and the others?
In the layered structure the direction of dependency points from top to bottom; in the hexagonal one the dependency points inward: the adapters depend on the ports, the core does not depend on the adapter. The hexagonal structure does not split into services: it lives in the same deployment unit, and the module of a modular monolith can also have such an internal structure (2.4). The "onion" and "clean" architectures, which work on a similar principle, are often mentioned too; they handle the direction of the internal dependency similarly, but the course does not discuss them separately.
By aspect
Common misconceptions
In short
Review questions
Learning resources