Ports & Adapters (aka hexagonal) architecture explained (2024)

Introduced by Alistair co*ckburn in 2005 as an alternative to the traditional layered architecture, the Ports & Adapters architecture clearly separates core logic from the input and output infrastructure, dividing the system into loosely-coupled interchangeable components. Throughout the years, it grew in popularity to become one of the most widely recognized types of software architecture.

Who is Alistair co*ckburn and why should I care what he thinks?

Other than introducing the Ports & Adapters architecture, Alistair co*ckburn is known for helping write the Manifesto for Agile Software Development in 2001. He is a co-founder of the International Consortium for Agile, and creator of the Heart of Agile concept.

First things first – forget the hexagon

To have an easier time understanding this architectural pattern, it is best to understand that while the Ports & Adapters architecture is sometimes called Hexagonal architecture, the latter name comes only from the graphical convention used by Alistair that shows the core application component as a hexagonal cell. The number of sides of a hexagon does not matter and the architecture could just as well be represented by a pentagon or an octagon.

For this reason, I have purposefully decided to not use the hexagonal shape in this article.

The intent

To quote Alistair himself, the goal of Ports & Adapters is to:

Allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases.

Alistair co*ckburn, “Hexagonal architecture

This can be achieved by reducing coupling between the outside world and the core domain.

In practice, this means that business logic should be isolated from any infrastructure and framework code and be completely independent of them. This not only allows infrastructural code to become interchangeable without harming that domain but also makes it much easier to reason about the code, as the business intent is not lost in technical details. Interestingly, this unlocks new abilities for the project, such as being able to pair program with the business.

This architectural style goes hand-in-hand with Eric Evans’ Domain Driven Design and so it is a good idea to familiarize oneself with DDD to better understand what the core domain should comprise of and how to properly isolate it.

The principle

The main principle of the Ports & Adapters architecture is to have inputs and outputs on the edges of technology-agnostic code. Commonly, this technology-agnostic code is called “the Application” or “the Hexagon” (as it’s typically drawn as one). Being a practitioner of Domain-Driven Design, I think a better name for it is “the Domain”, as this is the heart of software where business logic lies. The domain should not hold any references to frameworks, technologies or real world devices and should contain all of the business logic of the application.

Any real world thing that the domain interacts with is called an actor. That could be a test case, a human user or a single-page app. There are two types of actors:

  • Driving (primary) actors – they use the domain to achieve a goal; e.g. a test case or a human user
  • Driven (secondary) actors – they provide functionality needed by the domain to achieve a goal

A driven actor can be either:

  • a Recipientonly receives information from the domain; e.g. a printer or message queue (as a publisher)
  • a Repository can both provide information to the domain and receive it; e.g. a database or file system
Ports & Adapters (aka hexagonal) architecture explained (1)

At the edges of the domain there are ports. A port can be considered a group of interactions with a specific purpose and should not make any assumptions in regards to its implementation. Like actors, there are two types of ports:

  • Driving (primary) port – specifies how the domain can be used
  • Driven (secondary) port – specifies what functionality the domain needs

Actors interact with the domain ports through adapters, which plug into the ports:

  • a driving (primary) adapter converts requests from a specific technology to technology-agnostic requests that the domain can understand; e.g. a test framework or GUI
  • a driven (secondary) adapterconverts calls from the domain into specific technology methods; e.g. an SQL adapter or a file system adapter

It could be said that the adapters are a translation layer between the domain and the outside world.

Ports & Adapters (aka hexagonal) architecture explained (2)

The recommended steps to developing a feature (in terms of what kind of adapters to use) in this architecture are as follows:

  1. test harness, mock driven adapters
  2. real driving adapter, mock driven adapters
  3. test harness, real driven adapters
  4. real driving adapter, real driven adapters
Ports & Adapters (aka hexagonal) architecture explained (3)

Following these steps, each port should have at least two adapters – one mock and one real implementation. As seen in Alistair’s live coding example with Thomas Pierrain, the mentioned “mock driven adapters” might very well just be mocks hardcoded into a test (e.g. using tools like Mockito).

In summary, the architecture consists of the domain with its ports, the external actors which interact with the application and adapters which adapt specific technology for use with the domain.

For an even more in-depth look at Ports & Adapters, I recommend the excellent write up by Juan Manuel Garrido de Paz, endorsed by Alistair co*ckburn himself.

Example implementation

Architectural examples are often not very prescriptive, leaving the reader to figure out the details on their own. The Ports & Adapters pattern itself is vague about the details. Because of this, I have decided to show a more complete implementation in the form of a package structure diagram for a web based application, in hopes of providing a more useful starting point.

While you are free (and encouraged) to use this in your own applications, bear in mind that this is just one interpretation of how the Ports & Adapters pattern could be applied. You might find very different implementations in the wild. The aforementioned Juan Manuel Garrido de Paz has a series of articles about using Java 9’s modules to implement this architecture.

Another important detail to note is that, as we are talking about packages and not modules, this example does not protect from violations of the structure. Unless they are made into modules, something like ArchUnit would need to be used to enforce it.

Finally, this example does not promote ports to their own sub-package and presumes that driving adapters can treat any public domain service as a driving port. Some may disagree with this design decision due to the application not having clearly defined ports. My current belief is this does a better job of promoting Domain Driven Design.

The topmost packaging in this example will be by feature – this will reveal intent of the application at first glance, making it much easier to navigate. Additionally, such an approach is more likely to follow the principles of package cohesion.

Ports & Adapters (aka hexagonal) architecture explained (4)

Each feature package, then, will be divided into:

  • domain where business logic is stored
  • adapters that drive or are driven by the domain
  • config that puts together the application, instantiating the adapters and domain services
Ports & Adapters (aka hexagonal) architecture explained (5)

At the lowest level, the domain will be divided into:

  • model where the domain model will be stored
  • services for all of the domain services (including driven ports which are Recipients)
  • repositories for driven ports which are Repositories
  • exceptions for all domain exceptions

adapters should look similar. For example, a REST http-api driving adapter might be divided into:

  • controllers where all of the controllers for the given feature are stored
  • model for the API model (Data Transfer Objects)
  • mappers which map the API model into the domain model and vice versa
  • exceptions for all API exceptions
Ports & Adapters (aka hexagonal) architecture explained (6)

This package structure should be a good starting point for most projects that deal with business requirements.

The diagrams as a PDF fileDownload

Further reading/watching

It’s always a good idea to cross-reference new information with other sources, both to broaden one’s understanding and to protect oneself from incorrect advice. With that in mind, here are some good articles and videos on Ports & Adapters:

Photo bySergio Capuzzimati

Related:

Ports & Adapters (aka hexagonal) architecture explained (2024)
Top Articles
Latest Posts
Article information

Author: Jeremiah Abshire

Last Updated:

Views: 5841

Rating: 4.3 / 5 (54 voted)

Reviews: 85% of readers found this page helpful

Author information

Name: Jeremiah Abshire

Birthday: 1993-09-14

Address: Apt. 425 92748 Jannie Centers, Port Nikitaville, VT 82110

Phone: +8096210939894

Job: Lead Healthcare Manager

Hobby: Watching movies, Watching movies, Knapping, LARPing, Coffee roasting, Lacemaking, Gaming

Introduction: My name is Jeremiah Abshire, I am a outstanding, kind, clever, hilarious, curious, hilarious, outstanding person who loves writing and wants to share my knowledge and understanding with you.