Hexagonal architecture

Hexagonal architecture is a software [architectural design pattern] devised by Alistair Cockburn in 2005.

Conceptually, hexagonal architecture is similar to Jeffrey Palermo’s [onion architecture] (2008) and Robert C Martin’s [clean architecture] (2012). All these architectural concepts share the same fundamental objective: the [separation of concerns], achieved by slicing systems into discrete [layers] and applying the [dependency inversion principle] at the boundaries between the layers.

Hexagonal architecture is defined as a system that uses the ports and adapters pattern to model all inputs to, and all outputs from, all the components of a system. The ports-and-adapters pattern is thus used for every interface that a software component has with the outside world.

An application will typically have many different inputs and outputs.

Hexagonal architecture

The choice of a hexagonal shape to represent this architectural concept is arbitrary. It suggests there are typically multiple inputs on the "driving" side of an application and multiple outputs on its "driven" side. In the context of [distributed software] or [modular monoliths], multiple services or components may interface with each other through connections made via their ports (using adapters), so the whole system – from a [conceptual] view – forms a honeycomb pattern.

Honeycomb pattern

Hexagonal architecture shares some similarities with domain-driven design, and indeed the two architectural styles can be combined. Like domain-driven design, hexagonal architecture proposes that software components are built around a core model of their domain. The central domain layer encapsulates the business logic.

Pros and cons of hexagonal architecture

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 Cockburn

One of the main advantages of hexagonal architecture is [testability]. Because all dependencies are hidden behind abstractions by design, it makes it easy to mock external systems, including GUIs and other input interfaces. All you need to do is create special mock adapters that fit the same ports as the real adapters.

Another benefit is [evolvability]. It becomes possible, for example, to change from a human-driven use of an application to batch-driven use. You just plug in different adapters to the existing ports. Likewise, it is relatively easy to change dependencies. For example, you can migrate from MySQL to PostgreSQL by changing the database adapter.

For the same reason, applications become less tightly coupled to any particular infrastructure or host environment. Thus, applications are more [portable].

For the ports-and-adapters pattern to effectively deliver these promised benefits, it is important that business logic does not leak into the ports-and-adapters layer. This is the same constraint as for [n-tier architecture], in which business logic should not leak into either the uppermost UI/presentation layer or the bottommost persistence layer.

The main trade-off is that hexagonal architecture adds a lot of [accidental complexity]. There is more code to maintain, and potentially more effort involved in running applications in development and other environments. This additional complexity may not be worthwhile for small, trivial applications.

References