Hexagonal Architecture Explained: How the Ports & Adapters Architecture Simplifies Your Life, and How to Implement it, Updated 1st Edition: Series on Object-Oriented Design
()
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."
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
Hexagonal Architecture Explained Rating: 0 out of 5 stars0 ratingsUnifying User Stories, Use Cases, Story Maps: The power of verbs Rating: 0 out of 5 stars0 ratingsDesign in Object Technology 2: The Annotated Class of 1994 Rating: 0 out of 5 stars0 ratingsLove Trio Trio de Amor Rating: 0 out of 5 stars0 ratingsThe Mini-Book on Use Cases: All You Need but Short: The Simplifying Series Rating: 0 out of 5 stars0 ratingsDesign in Object Technology: "Class of 1994" Rating: 0 out of 5 stars0 ratings
Related to Hexagonal Architecture Explained
Related ebooks
CQRS by Example: Master CQRS: Build Efficient and Scalable Systems with Real-World Examples Rating: 0 out of 5 stars0 ratingsMastering the Craft: Unleashing the Art of Software Engineering Rating: 0 out of 5 stars0 ratingsArchitecting ASP.NET Core Applications: An atypical design patterns guide for .NET 8, C# 12, and beyond Rating: 0 out of 5 stars0 ratingsArchitectural Metapatterns: The Pattern Language of Software Architecture Rating: 0 out of 5 stars0 ratingsSoftware Architecture with Kotlin: Combine various architectural styles to create sustainable and scalable software solutions Rating: 0 out of 5 stars0 ratingsLearning Software Architecture Rating: 0 out of 5 stars0 ratingsCase Studies in Design Patterns Rating: 5 out of 5 stars5/5Model-Driven Software Development: Technology, Engineering, Management Rating: 4 out of 5 stars4/5Mastering Java Design Patterns: Unlock the Secrets of Expert-Level Skills Rating: 0 out of 5 stars0 ratingsBuilding Apple Watch Projects Rating: 0 out of 5 stars0 ratingsSwift 2 Design Patterns: Build robust and scalable iOS and Mac OS X game applications Rating: 0 out of 5 stars0 ratingsDesign Patterns in Practice: Unlock the Secrets of Expert-Level Skills Rating: 0 out of 5 stars0 ratingsDesign Patterns Made Easy: A Practical Guide with Examples Rating: 0 out of 5 stars0 ratingsASP.NET Core for Jobseekers: Build Career in Designing Cross-Platform Web Applications Using Razor and Entity Framework Core Rating: 0 out of 5 stars0 ratingsC# Data Structures and Algorithms: Harness the power of C# to build a diverse range of efficient applications Rating: 0 out of 5 stars0 ratingsObject-Oriented Analysis: Using Design Patterns Rating: 0 out of 5 stars0 ratingsMastering Python Design Patterns: Craft essential Python patterns by following core design principles Rating: 0 out of 5 stars0 ratingsFacade Pattern in Software Architecture: Definitive Reference for Developers and Engineers Rating: 0 out of 5 stars0 ratingsTest-Driven Java Development Rating: 0 out of 5 stars0 ratingsPatterns, Principles, and Practices of Domain-Driven Design Rating: 0 out of 5 stars0 ratingsJavaScript Design Patterns: Deliver fast and efficient production-grade JavaScript applications at scale Rating: 0 out of 5 stars0 ratingsCompiler Frontiers Unveiled Rating: 0 out of 5 stars0 ratingsMastering the Art of Nix Programming: Unraveling the Secrets of Expert-Level Programming Rating: 0 out of 5 stars0 ratingsBeginning Rust Programming Rating: 0 out of 5 stars0 ratings
Systems Architecture For You
CompTIA Network+ CertMike: Prepare. Practice. Pass the Test! Get Certified!: Exam N10-008 Rating: 0 out of 5 stars0 ratingsGoogle Certified Professional Cloud Architect A Practical Study Guide to Master the GCP Exam Rating: 0 out of 5 stars0 ratingsCompTIA A+ CertMike: Prepare. Practice. Pass the Test! Get Certified!: Core 1 Exam 220-1101 Rating: 0 out of 5 stars0 ratingsEssential Computer Hardware: Understanding the Building Blocks of Modern Technology and Securing Your Digital World Rating: 0 out of 5 stars0 ratingsCompTIA ITF+ CertMike: Prepare. Practice. Pass the Test! Get Certified!: Exam FC0-U61 Rating: 5 out of 5 stars5/5Mainframe to Cloud Mastery: Best Practices: Mainframes Rating: 0 out of 5 stars0 ratingsCompTIA A+ CertMike: Prepare. Practice. Pass the Test! Get Certified!: Core 2 Exam 220-1102 Rating: 0 out of 5 stars0 ratingsMining for Knowledge: Exploring GPU Architectures In Cryptocurrency and AI: The Crypto Mining Mastery Series, #2 Rating: 0 out of 5 stars0 ratingsRaspberry Pi Projects For Dummies Rating: 5 out of 5 stars5/5The Official BBC micro:bit User Guide Rating: 4 out of 5 stars4/5Arduino Projects For Dummies Rating: 3 out of 5 stars3/5A Practical Guide for IoT Solution Architects Rating: 5 out of 5 stars5/5Generative AI for Cloud Solutions: Architect modern AI LLMs in secure, scalable, and ethical cloud environments Rating: 0 out of 5 stars0 ratingsMicroservices with Azure Rating: 0 out of 5 stars0 ratingsThe Ultimate Guide To Auto Cad 2022 3D Modeling For 3d Drawing And Modeling Rating: 0 out of 5 stars0 ratingsRaspberry Pi User Guide Rating: 4 out of 5 stars4/5Architecting Digital Transformation Rating: 5 out of 5 stars5/5Mastering Proxmox - Second Edition Rating: 0 out of 5 stars0 ratingsGame Boy / Color Architecture: Architecture of Consoles: A Practical Analysis, #2 Rating: 0 out of 5 stars0 ratingsThe Fundamentals of AI Rating: 0 out of 5 stars0 ratingsMainframe Meets Modernization: Mastering Hybrid Cloud Design: Mainframes Rating: 0 out of 5 stars0 ratingsMastering Kubernetes Rating: 5 out of 5 stars5/5DevOps for Networking Rating: 4 out of 5 stars4/5A Modern Enterprise Architecture Approach: Enterprise Architecture Rating: 4 out of 5 stars4/5The Book of Powershell Rating: 0 out of 5 stars0 ratings
Reviews for Hexagonal Architecture Explained
0 ratings0 reviews
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