Monday, 25 April 2016

Hexagonal != Layers

People around me know that I am a strong supporter of the hexagonal architecture (a.k.a. ports & adapters). Whether at work, during conferences or around coffee machines, I do not miss an opportunity to try to highlight the value of this architectural pattern created by Alistair Cockburn and which is DDD-friendly.

For me it's a real mystery: why almost no one actually leverages on hexagonal architecture, despite its huge ROI and value for projects...

During these discussions with people, a remark keeps coming again and again:
"... hexagonal and layers architectures are the same, right?"

Hell no! The aim of this article is to explain how different they are.

Some history about the "Layers" pattern

The concept of layers is not new in IT (eg OSI model), but the best description of this architecture pattern for me can be found within the POSA reference book (vol 1, published in 1996).

And like with any pattern, it is much more interesting to remember the intent / the problem to be solved than the solution. 

Otherwise there is a risk we use it because we know it instead of using it because it fulfills to our need...

I used to see many people using Layers by habit and without being able to justify why they use it. Let's make a test: ask colleagues who use it around you why they do it ;-)

Before comparing Layers with Hexagonal, let's resume the intent of the Layers architecture patterns: "helps to structure applications that can be decomposed into groups of subtasks in which each group of subtasks is at a particular level of abstraction."

The main objective: managing the complexity of a large application by decomposing it.

Now let's have a look at the solution: "Structure your system into an appropriate number of layers and place them on top of each other (...) observe the following rule: a J layer provides services used by its top Layer J+1 and delegates subtasks to its bottom layer J-1 (...) The main structural characteristic of the Layers pattern is that the services of Layer J are only used by Layer J+1; there are no further direct dependencies between layers."

The respect of the latter rule is crucial; it allows to limit the impact of the replacement of a layer with another one (only the top layer and possibly the bottom layer being impacted).

Although the pattern leaves open the number of layers, it is clear to me that the interest of the solution starts from 3 layers (for at least J,  J+1 and J-1). In fact in real life, you can usually count the number of layers within an application by knowing the number of tech leads previously involved on the project ;-) Leading to what we called a "Baklava architecture" (anti-pattern).

In the past I've worked on projects where there were so many layers... it was difficult to understand and follow the application / business logic.

I initially become interested in the Hexagonal Architecture to fix the poor signal / noise ratio found in those Layers architectures.

Hexagonal architecture: origin and usefulness

Created by Alistair Cockburn in the 2000s, the hexagonal architecture was designed to prevent the infiltration of the business logic into the UI code (such infiltration leading to less testable and more difficult to maintain apps).

The proposed solution is to divide our software in 2 distinct regions:
  • the inside (i.e. the business application logic)
  • the outside (i.e. the infrastructure code like the APIs, the SPIs, the databases, etc.).

2 distinct zones. No more, no less. 

Two distinct areas of our code with adapters positioned in what looks like a DMZ to protect the domain code from the infrastructure one. We just have to rely on the Dependency Inversion Principle (DIP) and the Repository pattern to prevent the domain code to be binded to the infrastructure code when it want to get some information outside, and voila!

Adapters? Ports?

There has been much debate on this subject but after few checks with Alistair and other happy few, the "port" describes something you don't code (i.e. a middleware API, a database driver, a springboot REST exposition, etc.) whereas the "Adapter" is what we code in order to bridge the 2 separated worlds: the infrastructure code where the adapter belongs and the Domain code the Adapter interacts with.

Since I already wrote a previous post about the Hexagonal Architecture , post a code sample of the hexagonal architecture but also made a talk with my friend cyriux (slides available here), I won't detail further here.

How the onion case complicates things

There is a variant of the hexagonal architecture: the onion architecture from Jeffrey Palermo.

To be honest, I don't really like this version which is mixing the concept of layers (like an onion) with the outsourcing of the infrastructure code as explained by Alistair.

As people usually only remember the "Layers" part, I think Jeffrey's pattern is misleading because it lead people to miss the most interesting part of the hexagonal pattern IMO (i.e. the segregation in 2 zones which simplifies everything).

Still not convinced that Hexagonal is not the same as Layers?

For sure you can mix both patterns by putting layers here and there within each of the 2 areas of the hexagonal architecture (like Jeffrey did), but I don't think you should. Indeed, this complicates the architecture of your system and has to be considered carefully (why would we do that? does it bring value in our context?).

Such mix-in would be our hybrid choice, and is not part of Alistair's description of the hexagonal pattern.

Can we say that 2 patterns with different motivations and different solutions are equivalent? 

Not in my opinion. What bothers me most with this speech is that it prevents people to discover the real power of the Hexagonal Architecture ("yeah, I don't see why I should look in detail this pattern, cause it's already what we do with our layers..."). Sad Panda.

According to me, the hexagonal architecture has two main virtues:

  1. To prevent domain code to be contaminated by the infrastructure code (DDD friendly)
  2. To simplify the architecture of our systems (avoiding the accidental complexity associated with extra layers for no explicit reason)

Fostering simplicity is hard but valuable

Hexagonal Architecture helps us to simplify our applications' architecture (and thus maintenance) by dividing it in 2 zones instead of a baklava architecture.

I like to finish that post with a tribute to Matteo Vaccari ASCII art comparison between Layers and Hexagonal. These diagrams helped me many times to explain those differences to colleagues at work.

Enough diagrams, let's see some code now!

I've published a few C# code samples of hexagonal architecture on my github space:

  1. On the (LunchBox) SimpleOrderRouting project as explained here
  2. In the CQRS (without ES) app sample published here (with its hexagon composition made here or like this in the acceptance tests)