Book cover

Web Version | Dark Mode | Cite

Software Engineering: A Modern Approach

Marco Tulio Valente

1 What is a Hexagonal Architecture?

1.1 Introduction

The concept of Hexagonal Architecture was first proposed by Alistair Cockburn in the mid-90s in an article posted on the WikiWikiWeb, the first wiki ever created (which primarily covered Software Engineering topics).

The goals of Hexagonal Architecture are similar to those of Clean Architecture, as we described in another article. Specifically, the idea is to build systems that have high cohesion, low coupling, and are easier to test.

A Hexagonal Architecture divides the classes of a system into two main groups:

Importantly, domain classes should not depend on classes related to infrastructure, user interface, or external systems. The main advantage of this division is to decouple these two types of classes.

As a result, the domain classes remain independent of the technologies–—including databases, user interfaces, and any other libraries–—used by the system. Consequently, technology changes can be made without impacting the domain classes. Perhaps even more importantly, domain classes can be shared across more than one technological platform. For example, a system may have various interfaces (Web, mobile, etc.). Furthermore, and equally important, it is easier to test the domain classes when they are decoupled from non-business-related classes.

In a Hexagonal Architecture, communication between the classes of these groups is mediated by adapters, which are classes that implement the same-name design pattern we studied in Chapter 6. We will further explain the role of the adapters shortly.

The architecture is usually represented by two concentric hexagons (see the following figure). The domain classes (or business classes, if you prefer) are in the inner hexagon. In the outer hexagon, we have the adapters. Finally, the databases and other external systems are located outside these two hexagons (and, thus, are not represented in the figure).

Hexagonal Architecture

Cockburn justifies the use of a hexagon as follows:

Each face of the hexagon represents some reason the application is trying to talk with the outside world. This is why it is concentric hexagons and not concentric circles.

Among the reasons that require communication with the outside world, we can mention the following: interacting with users (via a user interface, such as Web, mobile, console, etc.), persisting data, and sending data to other systems.

1.2 Ports and Adapters

In Hexagonal Architectures, the term port designates the interfaces provided or required by the domain classes (note that interface here means a programming language construct; for example, a Java interface).

There are two types of ports:

Finally, we have the components located in the outermost hexagon of the architecture—the adapters—that work in one of the following two ways:

1.3 Example: Library Management System

The following figure shows the hexagonal architecture of a library management system:

Hexagonal Architecture of a Library Management System

In the figure, we can see that users access the system using three interfaces: Web, mobile, and an external system. In all cases, this access is mediated by the adapters at the top of the figure. These adapters call methods defined in a port (or interface) provided by the domain. This interface might define methods for searching for books, making loans, and registering users in the library, among others. These methods are implemented by domain classes.

To fulfill its mission, the domain also needs to store and maintain data. For this purpose, it can use the services defined in a required port (or interface), which defines methods for saving and retrieving book data, saving and retrieving loan data, among other operations. An adapter in the bottom part of the figure implements these methods by accessing a relational database. Consequently, this database is an external system located outside the two hexagons.

In Hexagonal Architectures, we can have several required and provided ports, all located in the inner hexagon, along with the domain classes. Moreover, we have two types of adapters: (1) adapters that call methods defined in ports (or interfaces) implemented by the domain; and (2) adapters that implement the methods of a port (or interface) required by the domain.

1.4 Conclusion

In 2005, Cockburn suggested that his architecture could also be called Ports and Adapters Architecture, providing the following justification:

I finally had this aha! moment (June 2005) in which I saw that the facets of the hexagon are ports and the objects between the two hexagons are adapters […] and so the architectural pattern is Ports and Adapters Architecture. It admits of a better explanation than what I could come up with in Hexagonal Architecture.

However, this alternative name did not gain widespread adoption, and the architecture remains better known as Hexagonal Architecture.

More Info

We recommend two short articles by Alistair Cockburn on WikiWikiWeb. The first article discusses the main characteristics of a hexagonal architecture. The second article explores the concepts of ports and adapters.

For further reading, you can also refer to our article on Clean Architecture.

Exercises

1. In a Hexagonal Architecture, an adapter is an implementation of the same-name design pattern. What about the ports? Can they be seen as an approximate implementation of which design pattern? If necessary, consult Chapter 6 to answer.

2. In the figure illustrating the hexagonal architecture of the library management system, why are the user interface adapters (HTTP, GraphQL, and REST) and the persistence adapters (SQL) on distinct faces of the hexagon? Could they be placed on the same face?

3. The use of the term hexagonal is arbitrary, as depending on the application, it can be called quadrangular, pentagonal, heptagonal, octagonal, etc. Justify this statement.

4. The following code shows two domain classes used in the documentation of Django, a well-known framework for building web applications in Python. The code defines rules for mapping fields from these classes to columns of database tables. Does this implementation of domain classes follow the principles of a hexagonal architecture? Justify your answer.

from django.db import models

class Musician(models.Model):
  first_name = models.CharField(max_length=50) 
  last_name = models.CharField(max_length=50)
  instrument = models.CharField(max_length=100)

class Album(models.Model):
  artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
  name = models.CharField(max_length=100)
  release_date = models.DateField()
  num_stars = models.IntegerField()

5. Compare and contrast the Hexagonal Architecture with the Clean Architecture, which we studied in a previous article.


Check out the other articles on our site.