Hexagonal architecture pattern with banking example

Periasamy Girirajan Irisappan
4 min readJan 13, 2024

Hexagonal architecture, also known as Ports and Adapters architecture, is a software design pattern that aims to create a maintainable and adaptable system by structuring an application into loosely coupled, interchangeable components. This architecture has become a popular approach in software development, especially for applications that require a high degree of flexibility and scalability.

Key Concepts

  1. Central Core: At the heart of hexagonal architecture is the application’s core logic, often referred to as the business logic. This core contains the rules and procedures that define the application’s behaviour. It is isolated from external concerns like user interfaces, data storage, and external services.

2. Ports: Ports act as gateways for the application to interact with the outside world. They define the interfaces through which the core logic communicates. Ports can be categorized into two types:

  • Primary or Driving Ports: These are used by the application to expose its functionality to the outside world, like a REST API for a web application.
  • Secondary or Driven Ports: These are interfaces through which the application interacts with external components, like databases or message queues.

3. Adapters: Adapters are the implementations that connect the ports to external technologies or services. For instance, a database adapter might implement a secondary port to interact with a SQL database. Adapters ensure that the core logic remains decoupled from external concerns.

Advantages

  • Decoupling: By separating the core logic from external interfaces, hexagonal architecture enhances maintainability and flexibility. Changes in external technologies or UI frameworks have minimal impact on the core business logic.
  • Testability: The isolation of core logic makes it easier to write unit tests, as the business rules can be tested without worrying about external dependencies.
  • Scalability and Adaptability: Adapters can be easily replaced or modified to accommodate modern technologies or requirements, facilitating scalability and adaptability of the application.
  • Parallel Development: Different teams can work on separate adapters concurrently without affecting the core application, speeding up the development process.

Implementing Hexagonal Architecture

To implement a hexagonal architecture, developers should:

1. Define the Application’s Core Logic: Clearly define what constitutes the application’s business rules and processes.

2. Identify Ports: Determine the primary and secondary ports needed for the application.

3. Implement Adapters: Develop adapters for each port to manage the interaction with external technologies or services.

4. Keep the Core Isolated: Ensure that the core logic remains independent of external influences.

5. Test Rigorously: Utilize unit and integration tests to validate both the core logic and the interaction with external components through adapters.

Use Cases and Considerations

Hexagonal architecture is particularly useful for applications that:

  • Have complex business logic that needs to be kept separate from external concerns.
  • Require integration with multiple external systems or databases.
  • Need to be adaptable to changing technologies or requirements.

However, for smaller or less complex applications, hexagonal architecture might introduce unnecessary complexity. It is important to assess whether the benefits of this architecture align with the project’s needs.

Hexagonal architecture offers a robust and flexible approach to software design, promoting decoupling, testability, and adaptability. By structuring an application into a core with interchangeable ports and adapters, it enables developers to create systems that are easier to maintain, test, and evolve over time. However, its implementation should be considered in the context of the specific needs and complexity of the project.

Implementing an account service using hexagonal architecture involves structuring the service into a central core, ports, and adapters. Here is a step-by-step example to illustrate how this can be done:

Core Domain (Application Core)

The core domain of the account service contains business logic and rules related to account management. This includes functionalities like:

  • Creating a new account
  • Updating account information
  • Handling account balance
  • Managing transactions

This core is purely focused on business logic and is agnostic to how data is stored or how the user interacts with the system.

Ports

Ports in this architecture act as the interface between the core logic and external components. In the case of an account service, you might have the following ports:

Primary (Driving) Ports:

  • `AccountServiceInterface`: An interface for the basic account operations like creating, updating, and querying accounts. This could be exposed as a REST API for client applications.
  • Secondary (Driven) Ports:
  • `AccountRepository`: An interface for data persistence, handling CRUD (Create, Read, Update, Delete) operations for account data.
  • `NotificationService`: An interface for sending notifications (e.g., email or SMS) when certain account actions are performed.

Adapters

Adapters implement the ports and allow for interaction with external systems or technologies.

Primary (Driving) Adapters:

  • `WebAdapter`: Implements the `AccountServiceInterface` to expose the account services over a web interface (like REST API endpoints).

Secondary (Driven) Adapters:

  • `DatabaseAdapter`: Implements the `AccountRepository` interface to interact with a database, handling the storage and retrieval of account data.
  • `EmailNotificationAdapter`: Implements the `NotificationService` interface to send out email notifications.

Flow Diagram

1. User Interaction: A user or an external system interacts with the account service via the `WebAdapter`. This could be through a web application or another service making an API call.

2. Business Logic Execution: The `WebAdapter` translates the request into a format understood by the core domain, which then processes the request according to the business rules.

3. Data Storage and Notification: The core domain interacts with the database through the `DatabaseAdapter` for any data persistence. If the operation requires, it also communicates with the `EmailNotificationAdapter` to send out notifications.

4. Response: The core domain sends the result back through the `WebAdapter` to the user or the external system.

Benefits in this Context

  • Decoupling: The account service core logic is decoupled from the details of data persistence, external interfaces, and notification mechanisms.
  • Flexibility: Adapters can be easily replaced. For example, if you decide to change the database or the notification service, you only need to change the respective adapters without altering the core logic.
  • Testability: The core domain can be tested independently of external systems like databases or email services.

Conclusion

Using hexagonal architecture for an account service results in a flexible, maintainable, and scalable system. The separation of concerns provided by this architecture allows for easier adaptation to changing technologies or business requirements.

--

--

Periasamy Girirajan Irisappan

Im an IBM Dintiguished Engineer with 27 years experience in design and delivery of banking transformation projects in the areas of core modernization, digital