Explore 1.5M+ audiobooks & ebooks free for days

From $11.99/month after trial. Cancel anytime.

Hexagonal Architecture Explained: How the Ports & Adapters Architecture Simplifies Your Life, and How to Implement it, Updated 1st Edition: Series on Object-Oriented Design
Hexagonal Architecture Explained: How the Ports & Adapters Architecture Simplifies Your Life, and How to Implement it, Updated 1st Edition: Series on Object-Oriented Design
Hexagonal Architecture Explained: How the Ports & Adapters Architecture Simplifies Your Life, and How to Implement it, Updated 1st Edition: Series on Object-Oriented Design
Ebook289 pages2 hours

Hexagonal Architecture Explained: How the Ports & Adapters Architecture Simplifies Your Life, and How to Implement it, Updated 1st Edition: Series on Object-Oriented Design

Rating: 0 out of 5 stars

()

Read preview

About this ebook

Recommended by giants like Netflix and Amazon, the Hexagonal or Ports & Adapters architecture simplifies testing, protects against business logic leakage, supports changing technologies in long-running system, and lets you apply Domain Driven Design. In this definitive book on the subject, pattern author Dr. Alistair Cockburn and Juan Manuel Garrido de Paz lay bare all of the intricacies of the pattern, providing sample code and answering your many frequently asked questions.

"Looking at the screen of my laptop, I realized that it was full of code that didn't let me understand what it did regarding business logic. From that moment I began to search until I discovered the architecture that decouples the business logic from the frameworks: Hexagonal Architecture, more correctly called Ports & Adapters. From that moment until now, I haven't stopped reading and learning about this pattern."

LanguageEnglish
PublisherHumans and Technology Press
Release dateApr 15, 2025
ISBN9798998586217
Hexagonal Architecture Explained: How the Ports & Adapters Architecture Simplifies Your Life, and How to Implement it, Updated 1st Edition: Series on Object-Oriented Design
Author

Alistair Cockburn

Dr. Alistair Cockburn (pronounced CO-BURN) was named as one of the "42 Greatest Software Professionals of All Times" in 2020, as a world expert on project management, software architecture, use cases, and agile development. Besides co-authoring the Agile Manifesto, he wrote the award-winning books Writing Effective Use Cases and Agile Software Development: The Cooperative Game. In 2015, he created the Heart of Agile concept to be used in every kind of initiative, including social impact projects, governments, and families.

Read more from Alistair Cockburn

Related to Hexagonal Architecture Explained

Related ebooks

Systems Architecture For You

View More

Reviews for Hexagonal Architecture Explained

Rating: 0 out of 5 stars
0 ratings

0 ratings0 reviews

What did you think?

Tap to rate

Review must be at least 10 words

    Book preview

    Hexagonal Architecture Explained - Alistair Cockburn

    Chapter 1:

    Introduction

    1.1. Copy this code

    The Ports & Adapters architecture, first documented in 2005 as the Hexagonal Architecture pattern, demands this:

    Create your application to work without either a UI or a database so you can run automated regression-tests against it, change connected technologies, protect it from leaks between business logic and technologies, work when the database becomes unavailable, and link applications together without any user involvement.

    The most surprising part of implementing it is this requirement:

    Never explicitly name any external object or technology. Always take a parameter for any external object or technology you wish to access.

    That requirement has a weak and a strong implementation. In the weak implementation, the programmer knows that the database will use SQL (for example), and without tying to a particular database, still expresses the interface in SQL. While technically meeting the rules of the Ports & Adapters architecture, that still handcuffs the system to SQL, which is not what we are after.

    To get a full, or strong implementation of the Ports & Adapters architecture, we need:

    The app cannot know anything about the external technology.

    That is, the Service Provider Interface (SPI) or driven port is expressed purely in terms of concepts that make sense in the language of the domain. It can’t even know that there is a database, let alone SQL.

    The easiest way to show this is with a bit of code. The code is much simpler than all the discussions of why the code looks that way.

    Therefore, to get started, replicate this code snippet in your larger system. This Java code shows the interface definitions explicitly:

    interface ForCalculatingTaxes {

        double taxOn(double amount);

    }

    interface ForGettingTaxRates {

        double taxRate(double amount);

    }

    class TaxCalculator implements ForCalculatingTaxes {

        private ForGettingTaxRates taxRateRepository;

        public TaxCalculator(ForGettingTaxRates taxRateRepository) {

    this.taxRateRepository = taxRateRepository;

        }

        public double taxOn(double amount) {

            return amount *  taxRateRepository. taxRate( amount );

        }

    }

    class FixedTaxRateRepository

    implements ForGettingTaxRates {

        public double taxRate(double amount) {

    return 0.15;

        }

    }

    class Main {

        public static void main(String[] args) {

    ForGettingTaxRates taxRateRepository = new

    FixedTaxRateRepository();

    ForCalculatingTaxes myCalculator = new TaxCalculator(

    taxRateRepository );

    System.out.println( myCalculator.taxOn( 100 ) );

        }

    The preview edition contained a mistake. Without studying the previous code, see if you can find it in this original version:

    interface ForCalculatingTaxes {

        double taxOn(double amount);

    }

    interface ForGettingTaxRates {

        double taxRate(double amount);

    }

    class TaxCalculator implements ForCalculatingTaxes {

        private ForGettingTaxRates taxRateRepository;

        public TaxCalculator(ForGettingTaxRates taxRateRepository) {

    this.taxRateRepository = taxRateRepository;

        }

        public double taxOn(double amount) {

            return amount *  taxRateRepository. taxRate( amount );

        }

    }

    class FixedTaxRateRepository

    implements ForGettingTaxRates {

        public double taxRate(double amount) {

    return 0.15;

        }

    }

    class Main {

        public static void main(String[] args) {

    ForGettingTaxRates taxRateRepository = new

    FixedTaxRateRepository();

    TaxCalculator myCalculator = new TaxCalculator(

    taxRateRepository );

    System.out.println( myCalculator.taxOn( 100 ) );

        }

    I could say, almost comical, because Ricardo Guzmán Velasco (@RGVgamedev on Twitter) found it at the book launch. He came up and said he didn’t understand why I needed the driving port declaration. I went to explain, pulled my finger down the code, and went, Crap. He found the mistake within minutes of launch. Sigh.

    The mistake is giving myCalculator type TaxCalculator, that is, typing with the class instead of the interface. With that mistake, the interface definition at the top is meaningless.

    What followed over the next months was interesting. Some people wrote in and said that the interface declaration was important:

    Convention: It is the standard programming convention in languages that have that feature to type by interface, not class.

    The interface declaration is intended to provide the minimum interface that we want to expose.

    If every client couples to TaxCalculator, you lose the freedom to change its implementation. If you create another ForCalculatingTaxes implementation, you have to change all clients when you want to switch the implementation.

    The purpose of type-checking is to catch a certain class of errors at compile time. Declaring the type as the class and not the interface defeats the purpose of typing. You lose the safety you thought you were getting.

    Others wrote to say that there is no real problem in typing the variable with the class because for an app, the public methods are probably exactly the interface it should export, and you’re unlikely to make a second implementation of the app. Shoutout to Nicky Ramone (@nickyramone77) and Chris F Carroll‬ (@chrisfcarroll.bsky.social‬) for these insights.‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬‬

    For them, the interface declaration at the top is unnecessary, which means the published code is still not right.

    In the end, it seems there are two reasonable schools of thought, each with its own defenders.

    In one, declare and use the interface declaration:

    interface ForCalculatingTaxes {

        double taxOn(double amount);

    }

    class TaxCalculator implements ForCalculatingTaxes {

    … (public methods) …

    }

    class Main {

    ForCalculatingTaxes myCalculator = new TaxCalculator(

    taxRateRepository );

    }

    In the other, don’t declare it. Just use the class:

    interface ForCalculatingTaxes {

        double taxOn(double amount);

    }      (don’t write this code)

    class TaxCalculator {

    … (public methods) …

    }

    class Main {

    TaxCalculator myCalculator = new TaxCalculator(

    taxRateRepository );

        }

    My mistake was having a foot in each camp, declaring the interface and then not using it.

    In your life, decide which way you prefer to write.

    Not all languages require type declarations. In these languages, the code is much simpler. The following Ruby code shows how dynamic languages create the same system with no interface definitions:

    class TaxCalculator

      def initialize( tax_rate_repository )

          @tax_rate_repository = tax_rate_repository

      end

       def tax_rate( amount )

          @tax_rate_repository.tax_rate( amount )

      end

       def tax_on( amount )

          amount * @tax_rate_repository.tax_rate( amount )

      end

    end

    class FixedTaxRateRepository

      def tax_rate( amount )

        0.15

      end

    end

    tax_rate_repository = FixedTaxRateRepository.new

    my_calculator = TaxCalculator.new( tax_rate_repository )

    puts my_calculator.tax_rate( 100 )

    puts my_calculator.tax_on( 100 )

    It will take the rest of this book to explain how that little bit of code is constructed, why it is done that way, and how to make it work in your setting.

    That doesn’t mean you should wait until you’ve read the whole book before getting started. We recommend you start now by copying that code into your workspace and building from there. We also recommend you read Chapter 4.8: Where do I put my files? if you have any questions about folder structures.

    1.2. Short history of the pattern

    1988: Alistair unknowingly implemented Model-View-Controller in his Smalltalk prototype, but his C programmer didn’t. When the need arose to change the source of inputs, the C program had to be torn apart and rewritten. Pain #1.

    1994: On a fixed-price, fixed-time project involving an object-relational mapper, the infrastructure designers found they had to change their design to the SQL database to improve performance. As the application programmers were unable to substitute an in-memory test database, they instead shut down the project for several weeks and frantically rewrote their mapper. Pain #2.

    2000: Alistair visited a friend who was having trouble with all the variants and versions of his application, with different input sources and notification methods. Those problems were solved using the Ports & Adapters architecture.

    2005: Alistair finally implemented the pattern on a real project (using Spring) and wrote it up with code samples, giving it the more accurate name, Ports & Adapters.

    2015: The notions of driving and driven adapters were added, along with the naming convention for interfaces as for_doing_something.

    2022: The pattern as a special case of Component + Strategy was formulated, along with the required interfaces concept.

    2023: The more complete and accurate Configurable Receiver pattern replaced the earlier, slightly incorrect pattern Configurable Dependency.

    2024: Juan and Alistair complete their collaboration to bring you the preview edition of this book.

    1.3. Why the name Hexagonal Architecture?

    The name Hexagonal Architecture was a placeholder name I (Alistair) came up with years before I understood what the sides of the hexagon stood for. I just knew they had to be there. As a pattern name, it is not really appropriate, since the number six has no particular meaning. In practice you might have three, five, or any number of ports, not six. Additionally, a hexagon is just a geometric shape. It doesn’t show up anywhere in your software.

    So why the name, and why change it to the more descriptive Ports & Adapters?

    The best answer is what I wrote in the RSS feed from 2005, when I finally worked out what the facets meant:

    Somewhere in the mid-90s I started drawing a symmetric architecture in which the database is considered not at the bottom of the stack, but fully outside the application, just as we recommend doing with the user interface.

    To break up perceptions about top and bottom and left and right, I drew it with a hexagonal shape, and came up with the rather lame name HexagonalArchitecture --- simply because I could not identify think of what the hexagon meant, but knew it had to have facets, and no number smaller than 5 made visual sense (and pentagons are harder to draw than hexagons).

    Finally just worked out what the drawing meant and realized this picture or architecture should be called Ports and Adapters (think operating system or hi-fi ports, and Design Pattern adapters).

    -https://web.archive.org/web/20060318201137/http:/alistair.cockburn.us/rss.rdf (time stamp: 2005 07 15 13:01 MST)

    Hexagonal Architecture has served well as a hook to the pattern. It’s easy to remember and generates conversation. However, in this book we want to be correct: The name of the pattern is Ports & Adapters, because there really are ports, and there really are adapters, and your architecture will show them.

    1.4. The costs and benefits of this pattern

    There are many benefits to the Ports & Adapters, AKA Hexagonal Architecture, code structure:

    1.   Testing: You can write and run system-level tests without production connections, making them purer and faster.

    2.    More on testing: You can swap out the production connections for test connections, and vice versa—for any of the connections, input or output—without having to recompile your system.

    3.    Leakage protection: The test wall around your application will detect whenever someone leaks UI details or technology details into the business section, or business logic into the UI or external technology sections.

    4.    Large system separations: Different teams can develop their sections of code independently, test them separately, and connect them according to defined and tested interfaces.

    5.    Long-running systems: You can replace one external connection with another as technology and business needs change over a period of

    Enjoying the preview?
    Page 1 of 1