Table of Contents
Hexagonal Architecture and ports and adapters architecture is very used nowadays but a lot of people are confused with the names and are not sure what is the difference between them, what is their value proposition.
Hexagonal Architecture is an architectural style that moves a programmer’s focus from conceptual layers to a distinction between the software’s inside and outside parts. The inside part is use cases and the domain model it’s built upon. The outside part is UI, database, messaging, etc. The connection between the inside and the outside part of an application is realized via ports and their implementation counterparts are called adapters. For this reason, this architectural style is often called Ports and Adapters.
Hexagonal Architecture promotes the separation of concerns by encapsulating logic in different layers of the application. This enables a higher level of isolation, testability and control over your business specific code. Each layer of the application has a strict set of responsibilities and requirements. This creates clear boundaries as to where certain logic or functionality should sit, and how those layers should interact with each other.
Each side of the hexagon represents an input – port, for example HTTP, which uses an adapter for the specific type. It makes a clear separation between the domain model and the devices used for inputs and outputs.
3 components of Hexagonal Architecture
A domain model is a conceptual model, a representation of meaningful concepts to the domain that need to be modeled in software. The concepts include the data involved in the business and rules the business uses in relation to that data.
A port is an entry point, provided by the core logic. It defines a set of functions.
Port is the medium through which business logic is accessed. It is a use case boundary, for example Ports correspond to use-cases in the application. Simplest implementation of a Port can take form of an API layer.
Primary ports are the main API of the application. They are called by the primary adapters that form the user side of the application. Examples of primary ports are functions that allow you to change objects, attributes, and relations in the core logic.
Secondary ports are the interfaces for the secondary adapters. They are called by the core logic. An example of a secondary port is an interface to store single objects. This interface simply specifies that an object be created, retrieved, updated, and deleted. It tells you nothing about the way the object is stored.
An adapter is a bridge between the application and the service that is needed by the application. It fits a specific port. Adapters act as a layer which serve the purpose of transforming the communication between various external actors and application logic in such a way that both remain independent. In hexagonal architecture all the primary and secondary actors interact with the application ports through adapters. Primary actors are the ones which use system to achieve a particular goal whereas secondary actors are the ones which system uses to achieve primary actor’s goals.
In other words, a primary adapter is a piece of code between the user and the core logic. One adapter could be a unit test function for the core logic. Another could be a controller-like function that interacts both with the graphical user interface and the core logic.
A secondary adapter is an implementation of the secondary port, which is an interface. For instance, it can be a small class that converts application storage requests to a given database, and return the results of the database in a format requested by the secondary port.
Vaughn Vernon continued with the Hexagonal, or Ports and Adapters, architecture style, which was created by Alistair Cockburn. Alistair believes that architecture should allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases.
Vaughn is famous for his DDD book and he sees hexagonal architecture as an evolvement of the layered style but with advantages. It allows for delaying decisions for certain architectural mechanisms, for example what kind of persistence to use without impeding the progress of building functionality. Main point here is that thinking in terms of ports and adapters make it easier to use the same internal API for different kinds of clients.
He sees that the main aim of this architecture is to decouple the application’s core logic from the services it uses. This allows different services to be “plugged in”, and it allows the application to be run without these services.
Benefits of Hexagonal Architecture
- Agnostic to the outside world
The application can essentially be driven by any number of different controls. You can use your inner core business logic through a Command Line Interface, another application or system, a human or an automated script.
- Independent from external services
When your application is agnostic to the outside world, it also means it is independent from external services. You can develop the inner core of your application long before you have to think about what type of database you are going to use. By defining the Ports and Adapters for your database, you are free to use any technology implementation. This allows you to use an in-memory datastore in the early days, and then make the decision of what type of database you want to use when you actually need to store your application’s data in persistent storage.
- Easier to test in isolation
Now that your application is agnostic to the outside world, it is much easier to test in isolation. This means instead of sending in HTTP requests or making requests to a database, you can simply test each layer of your application, mocking any dependencies. This not only results in quicker tests, but it also massively decouples your code from the implementation details of the outside world.
- The Ports and Adapters are replaceable
The role of the Ports and Adapters is to convert requests and responses as they come and go from the outside world. This conversion process allows the application to receive requests and send responses to any number of outside technologies without having to know anything about the outside world. It makes it possible to replace an adapter with a different implementation that conforms to the same interface.
- Separation of the different rates of change
The outermost layers that typically change the most. For example, the User Interface, handling requests or working with external services typically evolves faster than the business rules of the application. This separation enables you to quickly iterate on the outer layers without touching the inner layers that must remain consistent. The inner layer has no knowledge of the outer layer and so these changes can be made without disrupting the code that should not change.
- High Maintainability
Maintainability is the absence of technical debt. Changes in one area of an application don’t really affect others. Adding features do not require large code-base changes. Adding new ways to interact with the application requires a few changes. Testing is relatively easy.
To sum things up, Hexagonal Architecture is an approach that divides software into an inside and an outside part. By applying this approach, you make your most important code free of unnecessary technical details and we gain flexibility, testability, and other important advantages that make your working process more efficient.
If you are interested in software architecture, I recommend you subscribe to our monthly newsletter to receive the latest trends and best practices.