Hexagonal Architecture

Hazar Gul Nazari
5 min readSep 10, 2023

--

What is Hexagonal Architecture?

In the list of so many variants of codebase structures and code architecture, Hexagonal is one of the contenders that has received some attention in recent years. This structural architecture answers the need for low coupling and maintainability of the codebase as the codebase increases in complexity, features expansion, and team growth. I will explain each of them, but before that, I should mention that the Hexagonal Architecture is not the only architecture that fulfills the need for decoupling, maintainability, managing code complexity, and more in a monolithic codebase, rather there are many of them e.g.:

  1. Event-Driven Architecture
  2. Layered Based Architecture
  3. Service Based Architecture
  4. Service Oriented Architecture
  5. Modular Monolith Architecture
  6. Microkernel Architecture
  7. And some other less-known architectures

In this post, I am focusing on Hexagonal Architecture to understand it better. Also, using the Spring Boot Application we could see what the structure of the codebase looks like, however, it's technology-neutral and you could apply it to other languages/frameworks.

History of Hexagonal Architecture

This architecture was introduced by Alistair Cockburn around the 2000s, and the evolution of this architecture style can be traced back to the challenges faced by software developers in creating adaptable and maintainable systems. Before diving into Hexagonal Architecture’s birth, it’s essential to recognize the backdrop against which it emerged. Traditional layered architectures, like the 3-tier model (Presentation, Logic, Data), were prevalent. These models were straightforward but led to tight coupling between business logic and the surrounding infrastructure, such as databases and UIs. This coupling made changes challenging, limiting adaptability.

Alistair Cockburn’s Insight: Alistair Cockburn, a notable figure in the agile and software development community, observed these challenges. He recognized the need for an architecture that could allow the core application (business logic) to remain isolated from external technologies, frameworks, and interfaces. This observation was based on the premise that while business rules remain relatively stable, the technologies supporting them evolve much faster. Around the early 2000s, Cockburn introduced the concept of the Hexagonal Architecture. He named it after the hexagon’s geometric shape, symbolizing the multiple ways (or ports) an application can interact with external agents or systems.

Key Principles:

Cockburn emphasized a few primary principles when he introduced the Hexagonal Architecture:

  1. Isolation of Business Logic: The heart of the application should be free from dependencies on external frameworks, databases, or other infrastructural concerns.
  2. Ports and Adapters: External communications should occur through well-defined ports. Adapters would then implement these ports to connect with specific external systems, thus serving as the bridge between the core application and the outside world.
  3. Bidirectional Interactions: While traditional layered architectures often implied a top-to-bottom flow, Hexagonal Architecture acknowledges that interactions can be bidirectional. This means the core application can be both the initiator (through primary/driving ports) and the receiver (through secondary/driven ports).
Diagram of Hexagonal Architecture
📂 student-application

├── 📂 src
│ │
│ ├── 📂 main
│ │ │
│ │ ├── 📂 java
│ │ │ │
│ │ │ ├── 📂 com
│ │ │ │ │
│ │ │ │ ├── 📂 studentapp
│ │ │ │ │ │
│ │ │ │ │ ├── 📂 application
│ │ │ │ │ │ ├── 📜 StudentService.java (orchestrates use cases related to students)
│ │ │ │ │ │
│ │ │ │ │ ├── 📂 domain
│ │ │ │ │ │ ├── 📜 Student.java (core domain entity for student)
│ │ │ │ │ │ ├── 📜 Grade.java (example of a related domain entity, e.g., student grades)
│ │ │ │ │ │
│ │ │ │ │ ├── 📂 ports
│ │ │ │ │ │ ├── 📂 primary
│ │ │ │ │ │ │ ├── 📜 StudentUseCase.java (primary/driving port interface for student operations)
│ │ │ │ │ │ │
│ │ │ │ │ │ ├── 📂 secondary
│ │ │ │ │ │ ├── 📜 StudentRepository.java (secondary/driven port interface for student persistence)
│ │ │ │ │ │
│ │ │ │ │ ├── 📂 infrastructure
│ │ │ │ │ │
│ │ │ │ │ ├── 📂 adapter
│ │ │ │ │ │ ├── 📂 primary
│ │ │ │ │ │ │ ├── 📜 StudentController.java (REST controller serving as a primary adapter for student operations)
│ │ │ │ │ │ │
│ │ │ │ │ │ ├── 📂 secondary
│ │ │ │ │ │ ├── 📜 JpaStudentRepository.java (JPA implementation of the StudentRepository interface)
│ │ │ │ │ │
│ │ │ │ │ ├── 📂 config
│ │ │ │ │ ├── 📜 DataSourceConfig.java (Database and JPA configuration)
│ │ │ │ │
│ │ ├── 📂 resources
│ │ ├── 📜 application.properties (standard Spring Boot configuration file)

├── 📜 .gitignore
├── 📜 pom.xml (Maven dependencies and project configurations)
├── 📜 README.md

Checkout the Demo Code on GitHub

Benefits of Hexagonal Architecture

  1. Decoupling: By separating the core logic of the application from external concerns, Hexagonal Architecture promotes a high degree of decoupling. This means changes in external systems or interfaces have minimal to no impact on the core logic.
  2. Testability: With a clear boundary established, it becomes easier to write unit tests for the core logic without needing to involve external systems. This architecture also facilitates integration tests by allowing you to replace real adapters with test adapters.
  3. Maintainability: A decoupled system is easier to maintain. When concerns are clearly separated, developers can make changes to one part of the system with confidence that they won’t inadvertently break unrelated features.
  4. Scalability: Hexagonal Architecture provides flexibility in scaling specific components of a system. If one adapter (e.g., a database or an external service) becomes a bottleneck, you can potentially replace or augment it without major changes to the core logic.
  5. Flexibility and Interchangeability: Adapters in the hexagonal architecture can be easily swapped out. For example, if you decide to change from one type of database to another, you only need to update or replace the corresponding adapter without touching the core domain logic.
  6. Clear Architecture: By explicitly defining boundaries and establishing clear ports and adapters, Hexagonal Architecture can lead to more readable and understandable code. New developers can quickly understand the structure and flow of the application.
  7. Focus on the Domain: Hexagonal Architecture encourages domain-driven design. The core of the system revolves around the domain logic, ensuring that business rules and logic remain central to the application.
  8. Adaptability: It’s easier to adapt to new technologies or external interfaces. For instance, if a new messaging system or a new type of database becomes popular, you can integrate it by writing a new adapter without the need for massive rewrites.
  9. Parallel Development: Since the core logic is decoupled from external systems, multiple teams can work in parallel. One team can focus on the domain logic while another works on the external interfaces or adapters.
  10. Consistency: By applying the same pattern throughout the application, there’s a consistent approach to how external systems and services are integrated, leading to fewer surprises and a steeper learning curve for developers.

As software development evolved, with increasing complexity and rapidly changing technologies, the concepts proposed by Hexagonal Architecture became even more valuable. The ability to swap databases, change UI frameworks, or integrate with different third-party services without altering the core business logic resonated with many architects and developers. In Today's era, Hexagonal Architecture is now one of the foundational patterns discussed in software architecture. It’s particularly popular in Domain-Driven Design (DDD) circles and among developers who focus on testability and adaptability.

--

--

No responses yet