4.6 KiB
Hexagonal Architecture (Ports & Adapters) – Reference Manual
Overview
Hexagonal Architecture, also known as Ports and Adapters, is a software design pattern that isolates an application’s core business logic from external systems such as user interfaces, databases, frameworks, and third-party services.
The application is conceptually placed at the center (often drawn as a hexagon). All communication with the outside world happens through ports (abstract interfaces), which are implemented by adapters.
The key idea:
The domain does not depend on technology. Technology depends on the domain.
Fundamental Principles
1. Business Logic First
The core domain represents the real business rules and use cases. It must:
- Be independent of UI, databases, frameworks, and delivery mechanisms
- Express what the system does, not how it is delivered
2. Explicit Boundaries
All interactions between the core and external systems cross explicit boundaries (ports). This prevents accidental coupling.
3. Dependency Inversion
Dependencies always point inward, toward the core. External components depend on abstractions defined by the core.
Core Concepts
Domain (Core)
The domain contains:
- Business entities
- Value objects
- Use cases / application services
- Domain rules and policies
It contains no technical concerns such as HTTP, databases, file systems, or frameworks.
Port
A port is an abstract interface defined by the core.
Ports describe:
- What the application needs from the outside world (output ports)
- What the application offers to the outside world (input ports)
Ports are defined in the language of the domain, not infrastructure.
Examples (conceptual):
- “Store an order”
- “Send a notification”
- “Execute a checkout use case”
Adapter
An adapter is a concrete implementation of a port using a specific technology.
Adapters translate:
- External representations → domain concepts
- Domain requests → external system calls
Adapters are replaceable and exist at the system’s edge.
Adapter Types
Primary (Driving) Adapters
- Initiate interaction with the core
- Examples: Web UI, CLI, REST controller, automated tests
Secondary (Driven) Adapters
- Are used by the core
- Examples: Database repositories, message brokers, email services
Dependency Rule
- The core defines ports
- Adapters implement ports
- The core knows nothing about adapters
- Adapters depend on the core, never the reverse
This rule guarantees that business logic remains stable even when technologies change.
Interaction Flow
- A primary adapter receives input (e.g., user action)
- It calls an input port
- The core executes business logic
- The core calls output ports as needed
- Secondary adapters fulfill those ports using external systems
All I/O stays outside the core.
Structuring a System
A conceptual structure:
- Core
- Domain entities
- Use cases
- Port interfaces
- Adapters
- Input adapters (UI, API, tests)
- Output adapters (DB, services, files)
- Composition root
- Wires ports to adapters at startup
This structure is conceptual, not tied to folders or modules.
Testing Strategy
Hexagonal architecture enables strong testing practices:
- Test core logic using fake or in-memory adapters
- No need for databases or servers in unit tests
- Integration tests focus on individual adapters
Testing becomes simpler because dependencies are explicit and replaceable.
Benefits
- High testability
- Clear separation of concerns
- Technology independence
- Easier maintenance and evolution
- Multiple interfaces over the same core logic
- Strong alignment with Domain-Driven Design
Comparison to Layered Architecture
Layered Architecture:
- Organizes code by technical layers
- Often allows UI → DB coupling
- Business logic can leak into infrastructure
Hexagonal Architecture:
- Organizes around the domain
- Enforces strict boundaries
- Treats UI and DB as interchangeable details
When to Use
Hexagonal architecture is well suited for:
- Medium to large systems
- Long-lived codebases
- Complex business domains
- Systems with multiple interfaces
- Applications that must remain adaptable
It may be unnecessary for very small or trivial applications.
Summary
Hexagonal Architecture places the domain at the center and treats all external systems as replaceable plugins. By communicating exclusively through ports and adapters, it ensures long-term flexibility, maintainability, and testability.
This pattern is language-agnostic and focuses on design principles, not frameworks.