Software architecture
Before getting into the specifics of application architecture, it helps to understand the architectural patterns that shape how we organize code. When diving into software design, you'll often hear about Clean Architecture. It's almost become the de facto blueprint for designing maintainable systems. However, in my current work environment, Hexagonal Architecture is now a practical alternative. Let’s take a closer look at both, their nuances, and why Hexagonal might soon become even more popular.
Clean Architecture
Popularized by Uncle Bob, this pattern organizes code into four concentric layers:
┌─────────────────────────────────────────────────────────────────┐
│ Frameworks & Drivers (DB, Web, UI) │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Interface Adapters (Controllers, Gateways, Presenters) │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Application Business Rules (Use Cases) │ │ │
│ │ │ ┌───────────────────────────────────────────────┐ │ │ │
│ │ │ │ Enterprise Business Rules (Entities) │ │ │ │
│ │ │ └───────────────────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
- Enterprise business rules: Entities representing core business concepts.
- Application business rules: Use cases orchestrating entity interactions.
- Interface adapters: Converts data between layers. Includes controllers, presenters, and gateways.
- Frameworks & drivers: Infrastructure details (DB, Web, UI).
Why you'll often encounter Clean Architecture
- Widespread adoption: Its clear demarcation of concerns has led to extensive community and enterprise support.
- Ease of understanding: The layered approach mirrors traditional systems, making it accessible for those familiar with classic architectural patterns.
- Separation of concerns: By isolating business logic in the inner layers, the system remains resilient against external volatility.
Hexagonal Architecture
Also known as Ports & Adapters, this pattern by Alistair Cockburn shifts the focus to the interactions between the system and its external actors, organizing responsibilities across two distinct perspectives:
- Driver side (Left):
- Driver ports: Define how external actors interact with the app.
Example: REST API endpoints.
- Driver ports: Define how external actors interact with the app.
- Use cases: Business logic triggered by external input.
- Driven side (Right):
- Driven ports: Define how the app interacts with external services.
Example: Database access. - Adapters: Implementation details.
Example: MySQL implementation of repository interface.
- Driven ports: Define how the app interacts with external services.
What sets Hexagonal apart
- Flexible integration: By clearly separating the roles on the driver and driven sides, the architecture easily accommodates various interfaces and integration mechanisms.
- Improved testability: Isolating external interactions through well-defined ports simplifies testing—the core use cases can be driven with mocks or stubs without invoking actual external systems.
Recommended learning resource
I really recommend Alex Hyett's video "Hexagonal Architecture: What You Need To Know - Simple Explanation".
Comparison
| Aspect | Clean Architecture | Hexagonal Architecture |
|---|---|---|
| Conceptual Focus | Emphasizes clear directional dependencies | Focuses on segregating external interactions |
| Adaptability | Excellent for applications with well-demarcated layers in traditional enterprise setups | Excels in environments requiring dynamic integration options (APIs, messaging systems, GUIs) with clear separation of concerns |
| Adoption and Mindset | Widely adopted due to its intuitive design and clear separation of responsibilities | Increasingly popular in dynamic environments; offers a forward-thinking approach that adapts to evolving integration demands |
Both architectures insulate core business rules from volatile external changes. Choose Clean Architecture when you want strict layer-to-layer dependency direction; choose Hexagonal when your integration points change frequently and you need to swap adapters without touching the core.