There are many different methodologies, philosophies and ideologies when it comes to building web applications.
Probably one of the most common forms of web application architecture you will come across is Model-View-Controller. MVC is typically the first architecture you will encounter when you begin your journey of learning how to build web applications.
However, as with just about everything else in web development, there is a time and a place for certain methodologies. Just because a certain type of architecture works for one type of project does not mean it will work for everything.
One such alternative is known as Hexagonal Architecture (also known as Ports and Adapters). Hexagonal Architecture promotes the separation of concerns by encapsulating logic in different layers of the application. This enables a higher lever of isolation, testability and control over your business specific code.
In today’s tutorial we’re going to be looking at Hexagonal Architecture, how it works, what are the positives and negatives and when is a good time to use this methodology over other competing patterns of architecture.
What is Hexagonal Architecture?
Hexagonal Architecture is a form of application architecture that promotes the separation of concerns through layers of responsibility.
Each layer of the application has a strict set of responsibilities and concerns. This creates clear boundaries as to where certain logic or functionality should sit, and how those layers should interact with each other.
The most important aspect of Hexagonal Architecture is the inner core application that captures the business logic of the organisation. The inner core should encapsulate the business rules of the application in order to meet the requirements of the organisation.
Outside of the inner core you have layers of ports and adapters that capture messages from the outside world and convert them to appropriate procedures to be handled inside of the application. The resulting message from the application is then passed back through this layer of ports and adapters as an appropriate response.
This means the inner core of the application has no knowledge of the outside world and so the direction of dependency will only flow outwards.
What are the benefits of Hexagonal Architecture?
There are a number of benefits to choosing Hexagonal Architecture when building a web application.
Agnostic to the outside world
The first big benefit of Hexagonal Architecture is the fact that your application is now agnostic to the outside world. Typically a web application will be driven by HTTP requests through a browser. However, because the inner core does not know anything about the outer layers, the application can essentially be driven by any number of different controls.
This means you can use your inner core business logic through a Command Line Interface, another application or system, a human or an automated script.
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 of the outside world.
This adherence to common interfaces allows us to replace an adapter with a different implementation that conforms to the same interface.
Separation of the different rates of change
In a typical web application, it is the outer most layers that typically change the most. For example, the User Interface, handling requests or working with external services typically evolves at a much greater pace 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.
Independent of external services
When your application is agnostic to the outside world, it also means it is independent from external services. Many greenfield applications start by setting up the tables of a database. However the database is not important to the job of your application and so you shouldn’t build your application focused on conforming to an external service.
Hexagonal Architecture is agnostic to external services and so 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.
What are the drawbacks of Hexagonal Architecture?
However, as with just about everything else in life, when there are positives, there are also negatives.
A higher level of complexity
Building an application with multiple layers of abstraction will mean that the level of complexity will dramatically increase. This can often mean that the on-boarding process for new developers to get a handle on the architecture of the application can be longer.
Prematurely creating multiple layers of abstraction for an application can often be a bad thing. Part of the beauty of smaller application is how easy it is to cut across the different layers to get the job done.
The cost of indirection and isolation
Similarly, when you have many layers of indirection and isolation, the cost of building and maintaining the application can often be more costly than the benefits of the abstraction.
Isolation is usually a good thing when it comes to testing your application. For example, when you can mock the database, your tests will usually run faster as a consequence.
However optimising for isolation and indirection to make testing your application easier can have a detrimental effect on the design of your application. When you have multiple layers of indirection, it can often be difficult to get your head around what is actually going on in your application.
Most web applications don’t need that level of complexity
The majority of all web applications will only ever be used through a browser, will never switch databases and will never switch frameworks.
Whilst creating the potential to swap any implementation within the application stack can be a noble goal, achieving that goal can be a fools errand.
Unless you are building an application that will realistically need that level of adaptability, it is usually a waste of time to build your application around that ideal.
Hexagonal Architecture is just one of many methodologies for building web applications. As is common with a lot of these types of decisions, when and where to use Hexagonal Architecture really depends on the project in question.
I really like the ability to segment my application into different layers of responsibility. I think a lot of the growth pains of web applications comes from a lack of clarity in terms of division of responsibility.
However prematurely optimising for this type of growth is probably also a bad thing too. If you jump the gun with premature abstractions, you might never reach the stage of actually needing them.
The canonical resource of Hexagonal Architecture comes from Alistair Cockburn who coined the term.
Uncle Bob Martin also wrote an interesting blog post on the topic titled The Clean Architecture
And finally if video is more your thing, I really enjoyed the following two talks on Hexagonal Architecture.
The video that really introduced me to the methodology was Hexagonal Rails by Matt Wynne. You don’t need to be familiar with Rails to get value out of this talk.