Hexagonal Architecture is a type of software architecture which favors Domain Driven Design. This is not a post about Domain Driven Design per se but it is important to understand that the less technical issues mingle with business logic, the better. Hexagonal architecture aims at separating accidental complexity and essential complexity.

Why Gradle?

Gradle is a simple yet very efficient dependency management build system. Similar result could also have been achieved using Maven, sbt or any other dependency management system compatible with Java.

Example domain

Blogging platform

blogging For this example, I've chosen to implement a very simple blogging platform. It allows three actions.
  • Write a post
  • Read a post
  • Share a post

GitHub repository

The demo repository is located on GitHub

Modules of the blogging platform

  • domain : domain logic. Here a very simple blogging platform.
  • **persistence **: simple in-memory persistence used by the blogging platform.
  • facebook-connector and **twitter-connector **: connectors to share a blog post on Facebook and Twitter
  • webserver : HTTP web server for hosting the blogging platform using Ratpack
  • **service-locator **: utility module for searching and exposing Java Service Providers

Modularity in a hexagonal architecture

External modules are technology-centric. Since they focus on a specific adapter, they contain usually one technology. Testing these modules independently becomes relatively easy. The only thing there is to test is the bridge between the domain ports and the technology used for the adapter. Ports are not likely to change unless business logic requires a change. This is why testing the domain can be done using mocks or using integrated solutions. The tests should remain the same even though their run context change, the former being simpler as there is no boilerplate from settings up dependencies.

Dependencies are only a means to make the domain work. Technologies of dependencies can be changed while the business logic will usually remain. Dependencies and the domain have completely different lifecycles. Trading one technology for another should have nothing to do with changing business logic. Splitting modules is a means to achieve this.

Hexagonal-Architecture

Domain module

The domain module should never depend on an adapter. It can depend on utility modules like logging or data manipulation libraries.

Adapter modules

Adapter modules should always depend on the domain module as they should implement a port of the domain module. They too can depend on utility modules. They can also have shared module dependencies if needs are.

Running the application

In a layered architecture, the outside component is usually a framework that will call business logic and lower layers. But in a hexagonal architecture, the domain is king. It should also declare how to run the application.

In Java, the class containing the public static void main method should be in the domain. In order to run it, all modules should be on the classpath.

Using Gradle, a runtime module called app contains no code but requires all modules at runtime and specifies the main class to launch.

In order to launch the example application, execute the following.

gradle: app run

Build

Building this application using a proper build system can be fast as the domain module always build first and all other modules can run in parallel once their shared libraries are built. This is not a purpose of hexagonal architecture, but a rather nice benefit from having a clean architecture.

Deployment

Deployment has some of the same benefits as the build. Since modules are mostly independent, they can also be deployed independently as well as having their own versioning. Each module can have its own lifecycle. In a standard Java application, the application would have to be restarted, but in a composable environment like OSGI, module swapping could be done at runtime.

Multiple hexagons

To go even further, multiple applications can be architectured as hexagons and each hexagon could, therefore, talk to another through an adapter. A standard monolithic application could be split up into several parts, each having a clear specific domain. Conway's law states that

"organizations which design systems ... are constrained to produce designs which are copies of the communication structures of these organizations."

Splitting up domains and producing multiple hexagons is a way to follow Conway's law. This is important as sometimes applications are used for two different business purposes, each business has its own rules and language which can be antinomical and would make the software reflect this contradiction. Having two hexagons with a clear interface between the two helps to identify correlations between those two businesses.

Conclusion (TL;DR)

Hexagonal architecture helps keep a clear separation between pure domain logic and complexity from frameworks and libraries needed. Feel free to browse and run the sample application to grasp this concept. The hexagonal architecture also favors from Conway's law in that it helps software to be more domain oriented.