Command Palette

Search for a command to run...

Level 3 · 25 min

Hexagonal Architecture

Hexagonal Architecture (Alistair Cockburn, 2005) — also called Ports and Adapters — isolates the application core from all external concerns by defining explicit ports (interfaces) and adapters (implementations). The hexagon represents the application core, surrounded by adapters.

Ports and Adapters

A Port is an interface defined by the application core. Driving ports (left side of the hexagon): interfaces that external actors use to drive the application — the HTTP controller calls the OrderService port. Driven ports (right side): interfaces the application uses to call external services — the application defines an EmailPort interface, the infrastructure provides an SMTPEmailAdapter. The critical insight: the application core owns all port interfaces. External adapters implement ports defined by the core — the dependency points inward. The HTTP framework, database, and email service are all 'plugins' to the application core. You can swap any adapter without touching the core.

Domain Isolation

The application core (hexagon interior) contains: domain entities, use cases/application services, and the port interfaces they define. The core has zero dependencies on: Spring/Express/FastAPI (frameworks), Hibernate/Sequelize (ORMs), Kafka/RabbitMQ (messaging), PostgreSQL/MongoDB (databases), AWS SDK (cloud), HTTP/SMTP/gRPC (protocols). This isolation is the testability benefit: the entire application core can be tested as a pure unit — no mocks of Spring beans, no in-memory databases, no Docker containers. Tests run in milliseconds. The production adapters are tested separately with integration tests against real infrastructure. Martin's synthesis across architectures: 'Hexagonal Architecture, DCI, and BCE... all have the same objective, which is the separation of concerns.' The shared result: 'The business rules can be tested without the UI, database, web server, or any other external element.' The practical test: if running your domain logic tests requires starting a Spring context or a Docker container, your hexagon boundary has been breached. Cockburn's original insight was that the application should be equally drivable by users, automated tests, and batch scripts — all via the same driving ports, with no special test-only pathways. — Robert C. Martin, Clean Architecture (citing Alistair Cockburn)

Comparison with Clean Architecture

Hexagonal Architecture and Clean Architecture are closely related. Both enforce: application core is independent of infrastructure, inward-pointing dependencies, use of interfaces (ports) for external dependencies. Key differences: Hexagonal does not prescribe internal layering of the core (entities vs use cases) — it focuses on the core/outside boundary. Clean Architecture adds explicit layering inside the core (entities vs application layer). In practice, many teams combine them: Hexagonal for the core/outside boundary, DDD for modeling the domain inside the core. The test strategy is identical: test the core with in-memory adapters, test adapters with integration tests.

Key Takeaways

  • Driving ports: external actors call the application (HTTP → port). Driven ports: the application calls external services (port → database). Both point inward: the core owns all interfaces.
  • The application core has no framework dependencies. If your application service imports Spring annotations or Hibernate annotations, it is not hexagonally isolated.
  • The test strategy: test the hexagon (core) with in-memory adapters (fast unit tests). Test real adapters with integration tests (slow, real infrastructure). This gives you a fast test suite for the logic and a slower suite for the integration.

Code example

arch007.learn.codeExample