Decoupling your technical code from your business logic with the Hexagonal Architecture (HexArch)

French version: Architecture Hexagonale: Découplez votre logique métier de votre code technique (HexArch)

Business logic overboard!

In one of the companies I worked for, my team has been asked to port an old application on a brand new stack (like moving from an EAR/SQL app to a self-contained/NoSQL one). By studying it, we quickly realized that we had to redo the entire infrastructure… the new frameworks were so different from what was used ten years ago. In fact the only thing that didn’t have to change was the business logic. So it makes sense to reuse it, right?

classic layered architecture (1)
a classic layered architecture

After a deeper look, the maven module named model was only POJOs, totally anemic… and although there is also service module, the business logic is shared across all the layers, drowned in a lot of technical code (DAOs creation, Serialization, Pool management, etc…). And no way to properly extract this, some parts of the business were relying on the technical behavior of the old framework we tried to remove. And why? Because there was no clean separation between the technical code and the business logic.

Separation of concerns

We searched for a mean to achieve this separation, in a way that if one day we have to change again the stack, we can reuse totally the business logic. And one of our colleagues told us about the Hexagonal Architecture. One of the key concepts of this architecture is to put all the business models/logics into a single place. So if I go back over the previous schema we would have something like this:

overview of classic layered arch with domain

Another key concept is the domain depends on nothing but itself; this is the only way to ensure that the business logic is decoupled from the technical layers. How do we achieve that on the previous schema? The domain clearly depends on the persistence layer! Well by using a pattern you may know: the inversion of control. If we redo the previous schema with this – by calling the domain the Hexagon because Alistair Cockburn (creator of the HexArch) loves the shape – we will have something like this:

overview of hex arch

Ok the inversion of control was pretty magic, we will see later how it works. But now you got an overview of what is the Hexagonal Architecture:

  • Only two worlds, inside the Hexagon with all the business models/logics, outside the Hexagon: the infrastructure – meaning all your technical code.
  • The dependencies always go from outside toward the inside of the Hexagon, which ensures the isolation of the business domain (so it can be reused if you change later your infrastructure!).
  • One corollary of this is the Hexagon depends on nothing but itself, and not only regarding your own layers: It must not depend on any technical framework, including external annotations like Jackson or JPA. To ensure this if you use maven, you can use the enforcer plugin.

Let me explain you a bit more the last point, which is a really important one. In another experience, my team had to port an application from the “classic” Spring framework to Spring Boot. Spring Boot simplifies for you a lot of things; it means that it can be sometimes very different from the Spring framework. The main (painful) problem we had is that we were leveraging a lot on the Spring Integration Tests to validate our functionalities and those functionalities were relying a lot on Spring. And because we didn’t realize that Spring Boot had a special integration with some other framework we were using, the very first time we integrated it, all those tests were failing. We were not able to say if we broke the business logic somewhere or if it came from a pure technical problem. When we figured out that it was related to an integration problem at test level, we fixed all the tests one by one by crossing our fingers, hoping the domain was still correct.

By making sure the Hexagon doesn’t depend on any framework, your make sure that your business domain can be reused even if you decide to change your stack. You will as well increase the testability of your domain because you no longer mix it with integration problematics so you’ll do real functional tests. This way those tests will directly interact with the Hexagon and only with it; I’ll talk more about that later.

The magic trick of HexArch

Remember the inversion of control? In order to ensure the isolation of the Hexagon, the dependencies on downstream layers have been inverted. The trick is in fact pretty simple as you can see:

hexagon (15)

The outside of the Hexagon (the infrastructure) is divided in two virtual parts, the left side and the right side. On the left, you got everything that will query the domain (the controller, the REST layer, etc.) and on the right, you got everything that will provide some information/services to the domain (Persistence layer, third party services, etc.). To let the outside to interact with the domain, the Hexagon provides business interfaces divided in two categories:

  • The API gathers all the interfaces for everything that needs to query the domain. Those interfaces are implemented by the Hexagon.
  • The SPI (Service Provider Interface) gathers all the interfaces required by the domain to retrieve information or get some services from third parties. Those interfaces are defined in the Hexagon and implemented by the right side of the infrastructure. We will see that on some circumstances, the Hexagon can as well implement the SPI.

There are two important facts here:

  • The API and the SPI are parts of the Hexagon.
  • The API and the SPI only manipulate domain objects of the Hexagon, which ensures the isolation.

In a classic layered architecture, the Business Object or the service usually creates the DAOs of the Persistence layer like explained here. In the HexArch, the domain only handles domain objects. The Persistence layer is in charge to translate (adaptation) the domain objects into any technical objects to be persisted (through DAOs, annotated JPA POJOs, or whatever).

Can you feel the force?

The Hexagonal Architecture is also called the Ports and Adapters architecture. It comes from the power of the modularity of this architecture. Because everything is decoupled, you can have a SOAP, REST and JMS layers in front of your domain at the same time without having any impacts on it. On the SPI side, you can change from a MongoDB driver implementation to Cassandra if needed. Since the SPI won’t change because you change the persistence module, the rest of your software won’t be impacted. The API and the SPI are the Ports and the infrastructure modules using or implementing them are the adapters.

How to implement it?

One more rule here: always start with the inside of the Hexagon. This will bring you a lot of advantages:

  • Focus on the feature instead of the technical details. Because only the feature brings value to your company. A developer working on another business domain is able to put in place a Spring Controller. But the double declining balance method will sounds like Wookiee for him unless he worked for an accountancy company.
  • Delay choices on technical implementation. Sometimes it’s really hard to know which technical implementation you really need (like Spring Data, JPA, or Mongo vs Cassandra vs Redis, etc.). Delaying this choice helps you to focus on what brings the primary values to your company – the feature. Furthermore, after having implemented the business logics some new elements can help you to make the best choice regarding your infrastructure (e.g. more reads than writes or the domain is much more relational than expected).
  • One corollary is it ensures the Hexagon is a stand-alone I already talked a lot on the isolation, this is trivial now. Since you should never write code without tests, it means that the Hexagon is self-tested. Furthermore we got here real functional/acceptance tests focusing on the business only.

My advice is writing your functional/acceptance scenario first in a BDD/ATDD way. Then write the API interface which will be the entry point of your feature. Implement your tests (TDD for the win!) and after implement your business logic. You might need to define an SPI – to retrieve some data from the database for example – that’s fine go with it. And since the right side is not yet implemented, create a stubbed implementation of the SPI inside your Hexagon (e.g. an in memory database using a HashMap).

hexagon implementation (2)

You can choose to keep the Stubbed Implementation in the test scope of your application, or you can as well temporary ship it if needed. For example, once we have made the first feature on the Hexagon, we needed to stub an external third party service and the database. Because our client needed us to provide an interface contract, we secondly exported the domain through a REST controller. So we shipped a first version with stubbed data on the right side of the infrastructure but the client was able to see the structure of our data and the expected behavior of the feature. And it was much more reliable than creating by hand some JSON examples of what would be the input and the output of the feature because it actually deals with real business constraints.

The next step is usually opening the left side first. This way you can put in place some integration tests on the feature. At this time you can provide some live documentation and ensure an interface contract with your clients.

hexagon implementation left

Finally open on the right by implementing the SPI of your feature by taking advantage of the integration tests you made. I strongly recommend your tests to be stand-alone to avoid any instability during build time. You should always mock your third parties using something like Wiremock for external services or Fongo  to simulate a MongoDB.

hexagon implementation with right

Loop the same way for your other features.

HexArch in a nutshell

There is a real benefit in decoupling the business logic from the technical code. It ensures your business domain is durable and robust regarding the continuous evolution of the technology.

The Hexagonal Architecture offers you a real means to achieve this by:

  • Putting all the business models/logics in a single place.
  • The domain (the inside of Hexagon) is isolated and agnostic regarding the technical part (infrastructure outside the Hexagon) because it depends on nothing but itself. That’s why the dependencies always go from outside to the inside of the Hexagon.
  • The Hexagon is a stand-alone module. It increases the testability of your domain by writing real functional tests which don’t have to deal with technical problematics.
  • This architecture offers a powerful modularity, which helps you to write as many adapters as you want with low impact on the rest of the software. And since the domain is agnostic from the stack, the stack can be changed without any impact on the business.
  • By always starting with the inside of the Hexagon, you ensure to create quickly value to your company by making a focus on the feature development. This way you can delay choices on technical implementation so the best choice can be made at the right time.

Some feedbacks

Hexagonal Architecture should not be used in all situations. Like DDD (and HexArch matches very well with it), this is really applicable if you got a real business domain. For an application which transform a data to another format, that’s might be overkill.

To finish on this, always be pragmatic when you adopt a new technology. As stated before, the Hexagon must not depend on any technical framework, but exceptionally you can. For example in our case the Hexagon had three exceptions: Apache Commons Lang3 (StringUtils), SLF4J and the JSR305 of Findbugs. Because we didn’t want to create the wheel again and we felt that those frameworks had very low impacts on the domain. One good side effect of HexArch is that you keep challenging yourself before integrating a new framework. Before HexArch we got about fifty dependencies for the domain and it has been reduced to three or four of them. This is very good from a security perspective.

External links

You can also find here a great article on the Hexagonal Architecture: https://softwarecampament.wordpress.com/portsadapters/

8 Comments Add yours

  1. Juan says:

    Excellent article! It’s one of the best I’ve read about this subject. Congratulations. I do apply ports&adapters architecture in my projects too.

    Like

  2. A very nice write up indeed, especially the division between API/Domain/SPI.

    But I wonder whether it’s ok to expose my domain objects – which should provide rich business functionality – in the interface that’s inside the API? This would mean that the controller could invoke those business methods directly on the Entities it sees, without going through the API at all.

    So, should the API really use the domain objects directly or should it provide some DTOs, which will be mapped to domain objects in the implementation of those API interfaces?

    Like

    1. Hi Peter, thank you for your comment.

      API and SPI are interfaces uses to enter or step outside a domain. So usually those interfaces only uses domain objects. DTOs are usually used to transfer data over the network and are most of the time POJOs. With the Hexagonal Architecture philosophy, people generally uses DDD where POJOs are not recommended inside the domain.

      One of the main reason of that is, every domain objects have to be valid when they enter the domain. In DDD – thourgh the object oriented paradigm – this is ensured by the constructors of your domain objects.

      Another way to answer to you, in HexArch, everything inside the Hexagon is a part of the domain (business) and not technical. If the API is using DTOs, it would mean those DTOs are part of your domain objects, which doesn’t really make sense to me since they are dedicated to technically represent a domain object.

      Hope I was enough clear 🙂

      Like

      1. Juan says:

        Hello J’aime, I had the same question than Peter.
        I use HexArch with DDD. The inner of the hexagon isn’t just the domain, but the application layer too. The application layer and the domain model would be both inside the hexagon. The API of the hexagon would be the application layer of DDD. So putting DTOs there it would be ok. The Domain model is inner. The application layer would map DTOs to/from rich domain objects. Well that’s my approach, but I think that it is correct, because domain objects shouldn’t been exposed to adapters (infraestructure). The point is that the inside of the hexagon is layered into application and domain (application surrounding domain). Also, mapping would be made on the right side (persistence port), for translating domain model and persistence model.
        Regards,
        Juan.

        Like

      2. Hi Juan,
        In fact from what I saw with applications implementing Hexagonal Architecture, we get rid off the application layer which becomes a bit redundant.
        The main purpose of exposing your domain objects to the infrastructure, is to ensure the inversion of control. The other reason, you ensure this way to fail fast. So when your adapter is attempting to create an incorrect domain object, it will fail in the infrastructure.
        It doesn’t mean there is no reason to keep an application layer in the domain, as long as you can take advantage of it. Be careful to avoid any confusion with an application infrastructure layer (specially if you are using springboot).
        The only possible caveat I can see with that solution, is that you’ll have two representations of your domain concepts inside the domain, if I understood well what you did. One will be the real domain object and the second one the DTO.
        Thanks again for your comment.

        Like

  3. Juan says:

    Hi, you are wellcome, thanks to you for answering and talk about this subject. As I said before, your article is one of the best I’ve seen about hexagonal architecture. I like it. Some comments about what you said and what I think:

    ——————————————————–
    (1) “we get rid off the application layer which becomes a bit redundant”

    In my opinion you shouldn’t get rid of the application layer, it is not redundant, it should exist regardless of the achitecture pattern you use. It is the use case boundary and orchestrates domain objects. It cares about cross-cutting concerns like transactions. It is the direct client of domain model, and it isolates the domain from the outside world, keeping the domain impolute. It fits like a glove as the primary port (API of the hexagon) of hexagonal architecture. This architecture pattern says nothing about the structure inside the hexagon, it can be whatever you want. Alistair Cockburn uses to name the hexagon as the “App” (you can watch his “Alistair in the Hexagone” videos).

    ——————————————————–
    (2) “The main purpose of exposing your domain objects to the infrastructure, is to ensure the inversion of control”

    You can apply inverion control without exposing domain objects. You could expose just interfaces of the domain objects (representing just the state, not the behaviour).

    ——————————————————–
    (3) “Be careful to avoid any confusion with an application infrastructure layer (specially if you are using springboot)”

    I know. A Spring Boot application belongs to infraestructure. It is a primary adapter (MVC, REST API, CLI, TEST o whatever). It calls the primary port of the hexagon (API of the hexagon).

    ——————————————————–
    (4) “The only possible caveat I can see with that solution, is that you’ll have two representations of your domain concepts inside the domain, if I understood well what you did. One will be the real domain object and the second one the DTO”

    In the left side, there are DTOs belonging to the API port of the hexagon (the application service interface of DDD). These DTOs are not representations of domain concepts inside the domain, they collect plain data from the UI needed by a use case. The application layer maps from/to DTOs and domain objects.

    In the right side, there are “State Objects”. Unlike DTOs, according to Vaughn Vernon, this state objects do belong to the domain. They hold the state of “real” domain objects. The state is what the repositories persist.

    Regards,
    Juan.

    Like

  4. Juan says:

    Hi Julien. Thanks for adding a link to my article. Regards, Juan.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.