5. Hexagonal Architecture: Unraveling the Magic of Software Development
From my personal experience, the first time I heard about hexagonal architecture I asked myself: “What the hell is that, it sounds complicated” and I feel that is the thought of most developers who start in the world of this new architecture. Therefore, today we will explain what this architecture is about and we can see that it is not complex and difficult to understand and if we put it into practice, it will help us a lot in the development of projects.
What is hexagonal architecture ?
Hexagonal architecture is referred to as port and adapter architecture. Personally, I like to refer to the hexagonal architecture with the name of ports and adapters.
So… Why is it called hexagonal?
The creator Alistar cockburn tells us that: “The hexagon is not a hexagon because the number six is important, but rather to allow the people doing the drawing to have room to insert ports and adapters as they need, not being constrained by a one-dimensional layered drawing. The term hexagonal architecture comes from this visual effect.”
This architecture is a software design pattern that seeks to separate the business logic from the external implementation details. The main idea is to organize the system in layers, where the core of the application (the business logic) is at the center and communicates with the outside world through ports, which are implemented through different adapters that allow communication with external services.
The key to the hexagonal architecture is to decouple the code and apply the principle of dependency inversion. The principle of dependency inversion states that high-level layers should not depend on low-level layers, but on abstractions (interfaces or contracts). For this reason, ports and adapters play a fundamental role in this architecture. The main components of the hexagonal architecture are detailed below.
- Port: definition of an interface containing the methods that will be used by one or more adapters to implement them.
- Adapter: implementation of a port for a specific context.
How are the layers connected?
The following is a demonstration of how the connection works from the call of a controller to the communication with a database, in order to see how this architecture works in an easier way.
With the graph below, we can see in a more visual way how the communication between layers works with this architecture. However, let’s go into more detail to understand it further.
- Infrastructure: This layer contains the communication of services that are exposed to the world, such as database connections, drivers of our service, external APIs… etc. Therefore, this graphic as shown contains the use cases of controllers and database connections.
- Application: This layer as shown in the graphic contains the business logic and contains the ports that are allowed to connect to the infrastructure layer. Here, the application-specific use cases are defined and the interaction between the domain and infrastructure components is orchestrated. Therefore, in this case the ports become interfaces.
- Domain: The domain layer contains the entities belonging to the business logic and their corresponding rules. This layer, also called the core of the application, is where the main business logic and domain rules reside. Here the entities, value objects and domain services that represent the heart of the application are defined.
So far so clear right?….. However, you may have noticed that there are ports and adapters that are called input and others that are output. What does this type of separation refer to?
- Input: They represent the ways in which the application receives data or requests from the outside world. They are interfaces (ports) or implementations (adapters) that allow events or commands to reach the application core from the external environment. For example Controllers, Services
- Output: They represent the ways in which the application sends data, results or events to the outside world. They are interfaces (ports) or implementations (adapters) that allow the core application to report or provide information to the external environment.
With all this explained, I now know that we are much clearer on how the hex architecture works and how to understand the complex issue of ports and adapters. Now it’s time to put it to the test! 😄
How to apply this in a real project?
It is very nice to talk about the theory and concepts of hexagonal architecture, but at least what made me understand how this architecture works is applying it in a project.
With this in mind, here is the structure that I recommend to always start a project with hexagonal architecture. To achieve this you just have to create packages and organize it in such a way that it looks like in the figure.
With this small organization of packages we can start to make any hexagonal architecture project, since it meets the norms and standards of the architecture. Finally, I leave a repository on GitHub in which this organization is applied in a project with Spring Boot, which only does is to list and create users. Something simple but very practical to understand how this architecture works.
With all this explanation, I know that now you will understand better how this architecture works and how to apply it to a project. In my opinion I can draw the following conclusions.
Conclusions
- The use of this architecture allows us to practice SOLID principles in a practical way and to understand them in a better way.
- The hexagonal architecture allows us not to touch the business logic and only focus on modifying issues such as database connections, i.e., it gives us the flexibility to make changes without affecting the business.
- Although the hexagonal architecture is very efficient, it also suffers problems when scaling to many domain classes, so there are solutions such as Vertical Slices that I will talk about on another occasion.
I hope this article will be very useful!