Ports and Adapters Pattern (Hexagonal Architecture)

Published on August 29, 2018 by @jmgarridopaz


This article is for sharing my knowledge about Ports & Adapters pattern (also known as Hexagonal Architecture), hoping it can be helpful to someone interested in this subject. Here I expose my understanding of this architecture pattern, after being reading articles, watching talks and learning about it, since I first heard of it two years ago. This is a conceptual article, rather than a practical one. I hope to publish a pragmatic article soon, explaining my implementation of this architecture using Java 9 modules; and I hope to upload a proof of concept to github as well


TABLE OF CONTENTS

1.- Introduction.
2.- The Architecture.
2.1.- The Hexagon.
2.2.- Actors.
2.3.- Ports.
2.4.- Adapters.
2.5.- Summary.
2.6.- Example.
3.- Configurable Dependency Pattern.
4.- From “Symmetrical Asymmetry” To “Asymmetrical Symmetry”.
5.- Misconceptions.
5.1.- Layered Architecture.
5.2.- Why a hexagon?
5.3.- Ports outside Adapters.
6.- Pros and Cons.
6.1.- Pros.
6.1.1.- Testability improvement.
6.1.2.- Maintainability improvement.
6.1.3.- Flexibility.
6.1.4.- Application immune to technology evolution.
6.1.5.- Delay technological decisions.
6.2.- Cons.
6.2.1.- Complexity.
6.2.2.- Build process performance.
6.2.3.- Indirection and Mappings.
7.- When to “Hexagonal this!”.
8.- Implementation steps.
8.1.- Test driver adapters / Mock driven adapters.
8.2.- Real driver adapters / Mock driven adapters.
8.3.- Test driver adapters / Real driven adapters.
8.4.- Real driver adapters / Real driven adapters.
9.- Links.


1.- INTRODUCTION

Ports and Adapters is an Object Structural Pattern coined by Dr. Alistair Cockburn, in an article he wrote in 2005.

If you are thinking… “Isn’t the article too old? How is it that it is still worth it nowadays, being software development a discipline in continous evolution where new technologies and frameworks arise every day and kill the one we used yesterday?” Well the answer is in the question. Ports & Adapters is a pattern that promotes decoupling from technology and frameworks. So no, it isn’t too old. Good things are timeless. They are like wine, they get better as time passes by.

The main idea of Ports & Adapters is to define the structure of an application so that it could be run by different kinds of clients (humans, tests cases, other applications,…), and it could be tested in isolation from external devices of the real world that the application depends on (databases, servers, other applications, …).

Let’s see how to achieve this.


2.- THE ARCHITECTURE

In this section we will see the elements of Ports & Adapters pattern and the relationships between them.

2.1.- THE HEXAGON

Ports & Adapters pattern depicts the application as a closed area.

The closed area chosen by Alistair Cockburn for drawing the application was a hexagon, that’s why this pattern is also called Hexagonal Architecture.

Personally I prefer the name Ports and Adapters, because it refers to the key elements of the architecture, as we will see soon. On the other hand the figure you use for drawing the application isn’t important. However, it seems that the name Hexagonal Architecture is more popular.

The hexagon is the application itself. Saying “hexagon” and saying “application” is the same thing, from now on these terms will be used indistinctly.

Inside the hexagon we just have the things that are important for the business problem that the application is trying to solve.

The hexagon contains the business logic, with no references to any technology, framework or real world device. So the application is technology agnostic.

Ports & Adapters pattern says nothing about the structure of the inside of the hexagon. You can have layers… you can have components by feature… you can have spagheti code… you can have a Big Ball of Mud… you can apply DDD tactical patterns… you can have a single CRUD… it’s up to you.

2.2- ACTORS

Outside the hexagon we have any real world thing that the application interacts with. These things include humans, other applications, or any hardware/software device. They are the actors. We could say that actors are the environment of the application.

Actors are arranged around the hexagon depending on who triggers the interaction between the application and the actor:

  • Actors on the left/top side are Drivers, or Primary Actors. The interaction is triggered by the actor. A driver is an actor that interacts with the application to achieve a goal. Drivers are the users (either humans or devices) of the application.
  • Actors on the right/bottom side are Driven Actors, or Secondary Actors. The interaction is triggered by the application. A driven actor provides some functionality needed by the application for implementing the business logic.

There are two kinds of driven actors:

  • Repository: The application can also obtain information from it, besides sending. For example, a database or any other storage device.
  • Recipient: The application just sends information to it and forgets about it. For example, a SMTP server for sending emails.

The following picture shows some examples of actors in both driver and driven sides:

figure1

Figure 1: Actors

These concepts of primary (drivers) and secondary (driven) actors evoke use cases.

So, for knowing which kind is the actor in an application-actor interaction, ask yourself “who” triggers the conversation. If the answer is “the actor” then it is a driver. If the answer is “the application” then the actor is a driven actor.

2.3.- PORTS

The interactions between actors and the application are organized at the hexagon boundary by the reason why they are interacting with the application. Each group of interactions with a given purpose/intention is a port.

Ports should be named according to what they are for, not according to any technology. So, in order to name a port, we should use a verb ending with “ing” and we should say “this port is for …ing something”. For example:

  • This driver port is for “adding products to the shopping cart”.
  • This driven port (repository) is “for obtaining information about orders”
  • This driven port (recipient) is for “sending notifications”.

Ports are the application boundary, in the picture a port is an edge of the hexagon. From the outside world, actors can only interact with the hexagon ports, they shouldn’t be able to access the inside of the hexagon. Ports are interfaces that the application offers to the outside world for allowing actors interact with the application. So the application should follow the Information Hiding Principle. An important thing to remark is that Ports belong to the application.

Driver Ports offer the application functionality to drivers of the outside world. Thus, driver ports are said to be the use case boundary of the application. They are the API of the application.

Depending on the granularity we apply when grouping functionality, we can have a port interface with many use cases or with just a few. If we want to follow the Single Responsibility Principle, then we would have a lot of ports, each one for a use case. In this case a better option is applying the command bus design pattern to the port, with a command handler for each use case. Same idea could be applied to queries, so that we would satisfy the CQRS pattern as well. We would have a port for executing commands and another port for executing queries.

A driven port is an interface for a functionality, needed by the application for implementing the business logic. Such functionality is provided by a driven actor. So driven ports are the SPI (Service Provider Interface) required by the applicationA driven port would be like a Required Interface.

2.4.- ADAPTERS

Actors interact with hexagon ports through adapters using a specific technology. An adapter is a software component that allows a technology to interact with a port of the hexagon. Given a port, there may be an adapter for each desired technology that we want to use. Adapters are outside the application.

A driver adapter uses a driver port interface, converting a specific technology request into a technology agnostic request to a driver port.

Figure 2 shows some examples of driver adapters:

figure2

Figure 2: Driver Adapters

  • An automated test framework: Converts test cases into requests to a driver port.
  • A CLI  (Command Line Interface): Converts text entered in a console.
  • A GUI of a desktop application: Converts events triggered by graphical components.
  • An MVC web application: The Controller receives from the View the action requested by the user, and converts it into a request to a driver port.
  • A REST API controller: Converts REST API requests.
  • An event subscriber: Converts messages (events) from a message queue to which the application is subscribed.

For each driver port, there should be at least two adapters: one for the real driver that is going to run it, and another one for testing the behaviour of the port.

A driven adapter implements a driven port interface, converting the technology agnostic methods of the port into specific technology methods.

Some examples of driven adapters are shown in the picture:

figure3

Figure 3: Driven Adapters

  • A mock adapter: It mimics the behaviour of a real secondary actor, for example an inmemory database.
  • A SQL adapter: Implements a driven port for persisting data by accessing a SQL database.
  • An email adapter: Implements a driven port for notifying people by sending an email to them.
  • An App-To-App adapter: Implements a driven port for getting some data by requesting them to a remote application.
  • An event publisher: Implements a driven port for publishing events by sending them to a message queue, so that they are available for subscribers.

For each driven port we should write at least two adapters: one for the real world device, and another one a mock that mimics the real behavior.

What an adapter does in the end is to convert an interface into another, so we could use the Adapter Design Pattern to implement it.

Which adapter to use for each port is something that is configured at application startup. This is what gives flexibility to this pattern, so that we can switch from a technology to another everytime we run the application. If we choose a test driver and mocks adapters for the driven ports, it allows the application to be tested in isolation.

2.5.- SUMMARY

As we have seen, the elements of the architecture are:

  • The Hexagon ==> the application
    • Driver Ports ==> API offered by the application
    • Driven Ports ==> SPI required by the application
  • Actors ==> environment devices that interact with the application
    • Drivers ==> application users (either humans or hardware/software devices)
    • Driven Actors ==> provide services required by the application
  • Adapters ==> adapt specific technology to the application
    • Driver Adapters ==> use the drivers ports
    • Driven Adapters ==> implement the driven ports

Besides these elements, there will be a Composition Root (also called Main Component by Robert C. Martin, in his book Clean Architecture: A Craftsman’s Guide to Software Structure and Design). This component will run at startup and it builds the whole system doing the following:

  • It initializes and configures the environment (databases, servers, …)
  • For each driven port, it chooses a driven adapter implementing the port, and creates an instance of the adapter.
  • It creates an instance of the application injecting the driven adapters instances into the application constructor.
  • For each driver port:
      • It chooses a driver adapter that uses the port, and creates an instance of the adapter, injecting the application instance into the adapter constructor.
      • It runs the driver adapter instance.

2.6- EXAMPLE

Simple application with a web interface, used by the employees of a company for assigning tasks to each other. When an employee is assigned a task, the application sends an email to him/her.

figure4

Figure 4: An example (Task Assignement Application)


3.- CONFIGURABLE DEPENDENCY PATTERN

Configurable Dependency is a generalization of Dependency Injection, also called Inversion of Control.

It’s a new name coined by Gerard Meszaros. Alistair Cockburn considers it is a better name for the pattern, because it is a property, a characteristic. “Dependency Injection” is not a property, it is an action, it is the thing you do to achieve a configurable dependency. “Inversion of Control” is a double negative, like doing things wrong first and then inverting them.

Configurable Dependency fits the definition of what a pattern is:

“A pattern for something are common characteristics of good examples of something”

We could say that a configurable dependency is a dependency of an object on an interface. This interface would be an argument of the object constructor. Then, at runtime, a specific implementation of the interface is passed to the constructor when instantiating the object.

Hexagonal Architecture applies Configurable Dependency Pattern to both driver and driven side. In an actor-application interaction, the one that starts the conversation must know of the other, in order to know who to talk to, i.e. it must have a Configurable Dependency on an interface implemented by the other:

  • Driver side: The conversation is started by the driver (primary actor), so the driver adapter has a configurable dependency on the driver port, which is an interface implemented by the application.

  • Driven side: The conversation is started by the application, so the application has a configurable dependency on the driven port, which is an interface implemented by the driven adapter of the secondary actor

So dependencies are as follows:

figure5

Figure 5: Dependencies

  • A driver adapter depends on the hexagon (it uses a driver port interface).
  • A driven adapter depends on the hexagon (it implements a driven port interface)
  • Hexagon depends on nothing, maybe just on utilities of the programming lenguage.

Configurable Dependency is the most important pattern that Ports & Adapters Architecture is based on, as it allows the hexagon to be decoupled from any techonology. And this decoupling is what make possible the main goal of the architecture, that is, to have an application that can be run by several drivers and tested in isolation from recipients/repositories.


4.- FROM “SYMMETRICAL ASYMMETRY” TO “ASYMMETRICAL SYMMETRY”

Sounds quite confusing? If so, it’s ok, that’s what I wanted. Let’s explain it.

When the pattern was written in 2005, what the author wanted to show is that the asymmetry of the traditional layered architecture (user side vs data side), was in fact symmetrical. He did it by drawing an hexagon and putting both UI and database outside. Database is the same as UI, just technology, the application doesn’t know about it, like it doesn’t know about the UI.

Decoupling the application from the database is done by creating a driven port for it, and applying the Configurable Dependency Pattern by creating a driven adapter that implements the port. This way database depends on the application, and not the other way.

Then, when implementing examples of hexagonal architecture, the author realized that the symmetry was in fact asymmetrical, in the sense that the Configurable Dependency Pattern doesn’t apply the same way in the driven side than in the driver side.

In the driven side, the application must know about the driven adapter, because it’s the application who starts the dialog. It must know who to talk to.

On the other hand, in the driver side, it’s the driver adapter who must know about the application to start the dialog. The application doesn’t know which driver is driving it.

So what’s the conclusion? Is Ports & Adapters symmetrical or asymmetrical?

The corollary is that both symmetry and asymmetry coexists:

  • Symmetry: All the adapters, both driver and driven, depends on the hexagon. The application is technology agnostic in both sides.
  • Asymmetry: Configurable Dependency implementation is different for each side. In the driver side, the application doesn’t know about which adapter is driving it. But in the driven side, the application must know which driven adapter it must talk to.

5.- MISCONCEPTIONS

5.1.- LAYERED ARCHITECTURE

Many articles I’ve read about this architecture say that it is a layered one. They talk about three layers: domain, ports, adapters. I don’t know why they say such thing, the pattern says nothing about layers. The pattern just says that we have the application (the hexagon), with a given number of ports, and that for each port we can have different adapters, each one using a technology. There’s no layers nowhere.

5.2.- WHY A HEXAGON?

Some people wonder why a hexagon, perhaps thinking that the number of edges is important. Well the answer is no, it doesn’t matter at all. Number six isn’t important per se. Anyway, if you are curious, here you have some reasons by Alistair Cockburn on why he chose a hexagon:

  • You have enough space for drawing ports and adapters as you need.
  • The shape should evoke the inside/outside asymmetry rather than top/down or let/right. Then Squeare is not suitable. Pentagon, Heptagon, Octogon, … too hard to draw. So Hexagon is the winner.

5.3.- PORTS OUTSIDE ADAPTERS

I’ve seen many drawings where they put ports outside adapters, so that an actor interacts directly with the port, and then the adapter is the middleware between the port and the hexagon. This way:

Actor ===> Port ===> Adapter ===> Hexagon

This is not correct at all.

Ports are the hexagon boundary. In fact, they belong to the hexagon, they are part of it, they are interfaces of the hexagon. The actor interacts with the hexagon (the port) through an adapter. The adapter is the middleware between the actor and the port. The correct drawing is:

Actor ===> Adapter ===> (Port) Hexagon

And it is this way for both driver and driven sides. It is the symmetry of Port & Adapters pattern.


6.- PROS AND CONS

Modularity and application decoupling from technology are two important characteristics of Hexagonal Architecture. Such properties are the reason for both the advantages and the drawbacks. Here are some pros and cons I’ve found regarding of Hexagonal Architecture.

6.1.- PROS

6.1.1.- TESTABILITY IMPROVEMENT

The main benefit this architecture provides is the ability of testing the application in isolation from external devices it depends on. This is achieved by doing two things:

  • For each driver port, develop a test adapter that will run test cases against the port.
  • For each driven port, develop a mock adapter.

Testing the hexagon in isolation can be useful for:

  • Running regression tests. When source code changes for whatever reason (a new feature is added, a bug is fixed, …), these tests are run to ensure that those changes don’t have side effects on any already existing functionality. To run these tests, the driver adapter uses an automated test framework.
  • Doing BDD (Behaviour Driven Development). For each driver port functionality, a set of acceptance criteria is defined by the user. The functionality will be considered “done” when all the acceptance criteria are met. These acceptance criteria are called scenarios, which will be the test cases run by the test adapter. For running these acceptance tests the adapter can use tools like Cucumber.

Nat Pryce (co-author of the book Growing Object-Oriented Software, Guided by Tests) defines in his article Visualising Test Terminology different kinds of tests related to hexagonal architecture:

  • Unit Tests: For testing single objects inside the hexagon.
  • Integration Tests: For testing adapters. They ensure that translation between ports and the outside world is done by the adapters correctly.
  • Acceptance Tests: For testing driver ports, i.e. the hexagon in isolation. They check that application behaves as the user expects, meeting the acceptance criteria he/she previously defined for the use cases.
  • System Tests: For testing the whole system, adapters and the hexagon together. They also test system deployment and startup.
6.1.2.- MAINTAINABILITY IMPROVEMENT

Maintainable systems are those who are easy to modify. Hexagonal Architecture increases maintainability, because it provides separation of concerns and business logic decoupling, which makes it easier to locate the code we want to modify.

Application maintainability is a long term concept related to technical debt. The more maintainability the less technical debt. So, Hexagonal Architecture reduces the techical debt.

6.1.3.- FLEXIBILITY

Swapping between different technologies is easy. For a given port, you can have multiple adapters, each one using a specific technology. For choosing one of them, you just have to configure which adapter to use for that port. This configuration can be as easy as modifying an external configuration properties file. No source code modified, no re-compiling, no re-building.

Likewise, adding a new specific technology adapter to a port can be done without touching the existing source code. The adapter is developed and compiled on his own. At runtime, it will be detected and plugged into the port.

6.1.4.- APPLICATION IMMUNE TO TECHNOLOGY EVOLUTION

Technology evolves more frequently than business logic does. In applications where the business logic is tied to technology, you can’t do technology changes without touching business logic. This is no good, beacuse business should not change.

With hexagonal architecture, the technolgy you want to upgrade is located at an adapter outside the application. You just have to change the adapter. The application itself remains immutable because it doesn’t depend on adapters.

6.1.5.- DELAY TECHNOLOGICAL DECISIONS

When you start developing and coding, you can focus just on business logic, deferring decisions about which framework and technology you are going to use. You can choose a technology later, and code an adapter for it.

6.2.- CONS

6.2.1.- COMPLEXITY

A software project implementing Hexagonal Architecture has a complex structure, with lot of modules and explicit dependencies defined between them. By modules I mean source code subprojects (e.g. Maven modules) to physically separate the different elements of the architecture.

At least, there will be one module for the hexagon, one module for each adapter, and one module for starting up the whole project. You would also have to define the dependencies between modules: hexagon depends on nothing, adapters depend on hexagon, and the starting-up depends on all of them.

If the programming language doesn’t allow the hexagon to expose just the ports, then there would be even more modules. You would have to split the hexagon into ports and implementation. Hexagon implementation and adapters would depend on ports, and ports would depend on nothing.

6.2.2.- BUILD PROCESS PERFORMANCE

Due to the complexity we have just seen, if the project were too big, with lot of adapters, then the process of compiling, running tests, building all the modules together, and starting up the whole project would take a a lot of time.

6.2.3.- INDIRECTION AND MAPPINGS

Decoupling application from technology through ports and adapters adds indirection, i.e. extra calls to methods when an adapter converts between port and specific technology interfaces. Besides that, a mapping between application and ouside world objects, may be needed.


7.- WHEN TO “HEXAGONAL THIS!”

Or you could say it this way if you want: “When should Hexagonal Architecture be applied to a project?”. Well, the answer may be the most hated answer by silver bullet hunters: “It depends”.

  • For small projects, maybe “the cure is worse than the disease”, so that solving trivial problems doesn’t deserve the extra complexity added by the architecture.
  • For medium/large projects, which are supposed to have a long life cycle, and are supposed to be modified many times during their lifetime, using Hexagonal Architecture will be worth it in the long-term.

Some might say that they don’t need Hexagonal Architecture if they know for sure that the technology or frameworks used in the project are not going to change (e.g. because they are tied to a specific technology for some reason). Well, even in this case Ports and Adapters Pattern is useful, because you could add mock adapters to be used when devices/services the application depends on are not available, or you could add adapters for different runtime enviroments (development, test, production).


8.- IMPLEMENTATION STEPS

The starting point is the application as a black box, with ports interfaces defined around it, at both driver and driven sides, for interaction with the ouside world.

At the beginning maybe you still can’t define completely every driven port, as you still don’t know exactly all the needings the application will have regarding the purpose of the port. Or maybe you missed some driven port. But these needings will arise when developing the inside of the hexagon, i.e. the implementation of the driver ports.

So, for developing a hexagonal application from scratch, here is the order in which adapters are constructed and added at both driver and driven sides, until getting all done:

8.1.- TEST DRIVER ADAPTERS / MOCK DRIVEN ADAPTERS

  • Driver side: For each driver port, construct a test adapter, and implement the driver port driven by the tests. BDD can be used here for implementing driver ports, and the test cases would be GWT scenarios.
  • Driven side: When implementing a driver port, you may need to use driven ports. In such a case, construct mock adapters for them.

Once you have implemented all the driver ports and mocked the driven ports, you are done.

At this point the hexagon is complete, with tests at driver side and mocks at driven side. The application can be tested in isolation.

Next steps are for adding “real” driver and driven adapters for each port as you need, depending on the communication requirements with the outside world. For example, you may need Web UI and REST API adapters for the driver side; and SQL database and app-to-app adapters for the driven side. 

8.2.- REAL DRIVER ADAPTERS / MOCK DRIVEN ADAPTERS

  • Driver side: For each driver port, construct and add the “real” driver adapters you need. For example a Web UI, a REST API, …
  • Driven side: Keep the mock adapters you constructed in step (1).

This way you can test the new driver adapters.

8.3.- TEST DRIVER ADAPTERS / REAL DRIVEN ADAPTERS

  • Driver side: Configure each driver port with the test driver adapter constructed in step (1).
  • Driven side: For each driven port, construct and add the “real” driven adapters you need. For example a database adapter, an email notification adapter, …

This way you can test the new driven adapters.

8.4.- REAL DRIVER ADAPTERS / REAL DRIVEN ADAPTERS

  • Driver side: Configure each driver port with a “real” driver adapter constructed in step (2).
  • Driven side: Configure each driven port with a “real” driven adapter constructed in step (3).

This way you can test the application end to end, including “real” adapters at both driver and driven sides.

At this point you are done. You can configure every port with the adapter you wish, and run the application with any combination of ports and adapters configuration.


9.- LINKS

* Article by Alistair Cockburn defining Ports and Adapters Pattern:

http://alistair.cockburn.us/Hexagonal+architecture

* My translation of Alistair Cockburn article into spanish:

https://softwarecampament.wordpress.com/portsadapters-spanish

* Alistair in the Hexagone: a talk by Alistair Cockburn about Hexagonal Architecture:

https://www.youtube.com/watch?v=th4AgBcrEHA&list=PLGl1Jc8ErU1w27y8-7Gdcloy1tHO7NriL

* Interview with Alistair Cockburn about Hexagonal Architecture:

http://alistair.cockburn.us/Hexagonal+Architecture+FAQ

* An article I like about Hexagonal Architecture:

https://beyondxscratch.wordpress.com/2017/08/19/decoupling-your-technical-code-from-your-business-logic-with-the-hexagonal-architecture-hexarch

 

44 thoughts on “Ports and Adapters Pattern (Hexagonal Architecture)”

    1. Hi. You are wellcome. I read yours some time ago and I remember I liked it the most. I discussed with you some things in the comments, but it doesnt matter. I keep on liking it. Regards.

      Like

  1. Nice article!

    I have a question though: where/how would you implement transactions?
    Would you rather have some Transaction SPI (~ driven by the hexagon) or would you let the API client handle the transactional stuff (~ driver)?

    Thanks.

    Like

    1. Thanks Xavier.

      Well Hexagonal Architecture doesn’t say anything about transactions, the pattern just define the whole structure, it’s up to you to see where transactions fit. I will tell you what I think is the correct way:

      Driver ports are the use case boundary, so each “operation” (let’s call it “use case”) offered by a driver port should be transactional (enclosed in a transaction). But it’s not the client responsability to start/end transactions, it is the responsability of the use case implementation (i.e. the inside of the hexagon). Transactions are “technology”, so to deal with transactions the hexagon should call a driven port (you can create a new one or use the persistence port, as transactions are a database concern).

      How I do it: I use command pattern in driver port, and I have a decorator (wrapper) for enclosing every command in a transaction. This wrapper calls a TransactionSPI (driven port), which is implemented by an adapter that runs the command inside a transaction. In my case is just declarative transaction (the adapter use @Transactional Spring annotation), but it could be explicit, so that your adapter would do start/end/commit/rollback and that stuff.

      Hope it helps. I want to upload some code to github someday.

      Thanks for the comment.

      Like

      1. Juan,
        This is one of the best articles I have read so far concerning Ports and Adapters. I got some new insights and learned new things from it. Keep up the good work!
        I can’t wait to see some actual examples of how you implement this.

        Like

        1. Hello Jeffrey. Thank you very much for your words. I’m glad the article had been useful for you. I’m working in the example code, but time is never enough to get things done. It is just just a proof of concept though. Thanks again for your opinion, it makes me feel like I didn’t waste my time writing what I wrote.

          Like

      2. Did you ever upload an example of this to github? I’d love to see an example of tx management from within the hexagon.

        Like

  2. Hi jmgarridopaz,

    this is one of the best representations of the ports and adapaters archiecture.
    Main point for me was the clarification that
    (a) Application implements Driver Port, but
    (b) Driven Adapter implements Driver Port.

    Thank you!
    Bernd

    Like

    1. You’re welcome Bernd, thank you for reading and for your words about my article.

      What you point out in your comment is a usual misunderstanding people have. Some people think that a driver port is implemented by a driver adapter, and that’s wrong. Hope to upload a code example soon.

      PD: I guess you made a typo and you mean a driven adapter implements a driven port.

      Again, thank you.

      Regards,

      Juan.

      Like

  3. Hi Juan,
    Thanks for such a great effort and good explanation,
    I just want to ask whether is it necessary to seperate driven actors into two as you do in the following phrase?
    There are two kinds of driven actors:
    I mean is it important whether we get any response from driven actor?

    Regards,

    Cafer Lokum

    Like

    1. Hello Cafer, first of all sorry for the delay answering to your question. Second, thanks for your comment, it makes me feel like the effort I did is worth it, even more not being english my language. So, about your question:

      The separation “Repository vs Recipient” isn’t necessary. Whether or not we get any information from the driven actor is important in the sense that you have to know it for communicating with it, but you know it looking at the signatures of the API methods of the actor.

      They are new concepts that didn’t appear in the original article defining the pattern. First time I heard of them was in the talk “Alistair in the Hexagone” in 2017.

      Anyway, with those terms, Alistair Cockburn just wants to put it clear whether or not the driven actor provides information to the application. The interaction is always triggered by the app.

      A repository does provide info to the application (first the application has to ask for the info, and then the repository provides it).

      A recipient doesn’t provide info. The application just notifies or send something to the recipient, but the application doesn’t get any info from the recipient (in a sense, the application just “shoot and forget”).

      Some notes that come to my mind, and I would like to remark:

      – Here the concept “repository” has nothing to do with the concept repository of DDD (repository pattern).

      – By info I mean the info that is sent as a “goal” of the communication. For example, a printer is a recipient, the app sends commands or info (documents) to it. Besides that, maybe the app can read the status of the printer to check whether it is ok, but that’s not considered “info”. The app doesn’t want the printer for reading its status, but for printing documents.

      – The app can provide info to a repository too, not just the other way.

      – A database maybe is not always a repository. Imagine a write-only db for example, where the port just could insert, update, delete. It would be a recipient.

      – Repositories are not just databases. Another examples of repositories are: a remote app from which the application gets info, a file that the application reads.

      – To be a repository or a recipient, is kind of a “role”, in the sense that the same device can be a recipient for a driven port, but a repository for another port. Imagine for example a db that is write-only for a port, and read-write (or read-only) for other port.

      – Same for driver/driven actors: They are in fact “roles”. The same device can be a driver for a port, and a driven actor for another port. For example, imagine a message queue for sending events between applications. An app can publish events on a queue (driven actor), and can listen to events of the same queue (driver actor).

      Hope this explanation helps. Thanks again for asking and for your comment.

      Regards,
      Juan.

      Like

      1. Hi Juan,

        Thanks a lot for your kindly response,

        I understood it better after your explaination,

        In an enterprise application, I think that somehow we must check whether our interaction succeed or not. I got seperation between a repository and a receipt, but I think that we must somehow check whether receipt got our response or finished its responsibility.

        That was the reason for my question, but your explanation made it clear,

        Appreciate your efforts,

        Regards,

        Cafer

        Like

        1. Hello Cafer,

          well my explanation is just that, my thoughts about it, it’s just my opinion. I don’t consider checking whether the recipient received the info, enough reason to consider the driven actor a repository. Anyway, repository vs recipient classification isn’t important. What is important is driver vs driven.

          Thanks for reading.

          Regards,
          Juan.

          Like

  4. Hey! Thanks for this article. I’ve got some questions about the architecture. So I’m trying to create a poc of spring boot app based on this architecture, and I’m a lil bit confused about the dependencies. Where would fit the main class of the spring boot app? Inside the hexagon?
    Maybe I misunderstood something, but the application should not know about the plugged in adapters right? So what If I have a maven module called application which contains the application-services api and implementations and also have the main class of the spring boot app, then how this module will know the currently plugged adapters if the mentioned module is indepenendent from the adapters? I saw many examples on inet using this architecture, but the rest of them broke the main principles of it and I’m now really confused how to use it in the practice.

    The app what I created is a maven multi module app, which having these modules:
    -domain
    -application
    -adapter1
    -adaptern (adapters like: rest adapter, jpa adapter, mock db adapter (in memory))

    Do you have any idea or best practices for modularisation/separation?

    Best regards,
    Matt

    Like

    1. Hi Matt, thanks for your feedback and your questions.

      Spring Boot is “just technology”, a way of developing an application using Spring framework, you shouldn’t use it in the hexagon. Spring boot fits in any driver adapter (a MVC web app, a REST API, etc), and in the “main module” (startup, composition root, name it as you want) that builds the complete system (hexagon + adapters).

      I implement the architecture with the following maven projects:

      -HEXAGON: it depends on nothing, just on a custom lib with some Java language utilities I have for reusing (e.g. String utils). But this lib must depend on nothing.

      Each port would be a package with public interfaces.
      The rest of the hexagon shouldn’t be public classes, but private or default scope (no keyword), so that they won’t be visible outside the project.

      Another possibility is the hexagon as a multi-project, with childs: one child project for each port, and another one for the inside. The inside depends on the ports, and the ports depend on nothing.

      If you want to split the hexagon in layers (e.g. DDD layers), the inside would be as well splitted into two subprojects: application layer and domain model, with a dependency (application layer depends on domain model)

      -DRIVER ADAPTER: it depends on the hexagon (or on a driver port project if you have splitted the hexagon). It gets injected (uses) the driver port interface it depends on. It is an application per se, here you can use Spring Boot. It is run by the Startup project.

      -DRIVEN ADAPTER: it depends on the hexagon (or on a driven port project if you have splitted the hexagon). It gets injected (uses) the driven actor (a database, an external service, … whatever), and implements the driven port by calling to the driven actor functionality.

      -STARTUP (MAIN): it depends on all the other projects. It wires up the whole system: selects a driven adapter for each port, instantiates the selected driven adapters, instantiates the hexagon injecting the driven adapters, inject the driver port into the driver adapter, and finally it runs the driver adapter/s. Startup can as well be a Spring boot application.

      Another approach is to have Spring Boot on just the driver adapters. When you run a driver adapter, it looks for a class in the Startup project that will create a context, and the driver makes this context its parent, so that the driver adapter can use the beans. This is similar to what Spring Cloud does.

      I have some example projects about these approaches, but they are not published. If I have time, I will upload any of them to github.

      But now I’m working in a POC using Java 9 and modules. Hope to publish it not too late.

      Hope my explanation has helped you a bit.

      Thanks for reading.
      Regards Juan.

      Like

  5. Hello Juan. I really really ejoyed your article. It allows me a real understanding of Port and Adapters arquitecture. Until now I was applying the principles but I was not convinced, but from now Im know what Im doing. Thanks a lot pal

    Like

    1. Hi Armando. Sorry for my late answer. Thanks for your feedback. I’m really happy the article has been useful for you. It makes me feel like the time I spent writing was worth it. My intention was to explain the pattern clearly. Thanks for your words. Regards, Juan.

      Like

  6. Hi Juan,

    Great article, good job. Thanks for writing it.
    Can the hexagon and the adapters communicate over web like HTTP (via a RSEFUL API for example)

    Like

    1. Hi Abdoulie, thanks to you for reading and the feedback.

      The communication over http via a REST API would be as follows:

      Say you have a hexagon that wants to offer its functionality over http via a REST API to whatever client. Then the hexagon would have a “driver adapter” that offers the HTTP REST API, and translates an incoming http request to a call to a “driver port” of the hexagon, in order to perform the requested functionality. The driver port is an interface offering the use cases of the hexagon. The driver adapter is a RestController that depends on the driver port (interface) applying the Configurable Dependency Pattern, i.e., the driver adapter gets the driver port injected in its constructor.

      The client of the REST API can be another hexagon. This client hexagon would have a “driven port” (interface) for getting the info it needs, without knowing it will get it from the REST API of another hexagon. To access the remote REST API you would have a “driven adapter” implementing the driven port. The implementation will do the http request to the REST API. At runtime, the client hexagon gets injected the driven adapter.

      I’m preparing an implementation example, proof of concept, of the hexagonal architecture pattern, with source code at github and an article explaining it. I hope to publish it as soon as possible.

      Thanks for reading and for your question.

      Regards,
      Juan.

      Like

      1. How would you get the response back to the client when the controller wouldn’t get a return value from the port (since results will be handed over to a driven adapter)?

        Like

        1. Hi Willi,

          a driver port can return a value to the driver adapter. The information flow can be in both directions.

          For example, the driver port method can take a “Request” object and can return a “Response” object. These objects are DTOs. Another example is a “Query” method.

          I think the misunderstanding is with the interaction triggering. The comunication between the driver adapter and the driver port, is always started by the driver adapter, but then the information can flow in both directions.

          Thank you for reading and interacting.

          Regards,
          Juan.

          Like

  7. Hi Juan,
    I had a real pleasure reading your article as lots of concepts were explained clearly and carefully. Thank you!
    I’m a little bit confused about the configurable dependency pattern; how is it different from the dependency injection pattern in term of implementation?

    Best regards,
    Rahina

    Like

    1. Hello Rahina,

      first of all, sorry for the delay answering your question.

      You’re wellcome, I really appreciate your feedback, thank you very much for your words.

      Don’t be confuse about the Configurable Dependency Pattern, it is just a name for the pattern, that Alistair Cockburn considers more suitable than “dependency injection” or “inversion of control”. The pattern name would be “Configurable Dependency”, and “Depedency Injection” would be a way of implementing the pattern (another way of implementing it would be “Dependency Lookup”).

      The implementation would be to make a class depend on an interface (which would be an arg of the class constructor), and then at runtime the main component that builds the whole system instantiates a class implementing the interface and injects it in the constructor.

      Hope my answer helps you.

      See this URL where Alistair Cockburn talks about the configurable dependency pattern:

      https://web.archive.org/web/20170624023207/http://alistair.cockburn.us/Configurable+Dependency

      Regards,
      Juan.

      Like

      1. I see. At first I was wondering whether to revisit the implementation and in this case which element… Well I’m glad to know that it’s just a matter of terminology.

        Thanks for your reply!

        Regards,
        Rahina

        Like

  8. Hi Juan,

    I’m back again with another question. It may be obvious for most of you but I’m really struggling with the differences between hexagonal and layered architecture in term of the dependencies on the right side (driven). What is different about the dependency injection with hexagonal and the one in the layered architectures (not about the implementation, but the concept itself)? what’s new about the hexagonal (still on the driven side)?

    Best regards,
    Rahina

    Like

    1. Hello Rahina.

      In the classic layered architecture, the “business logic” (BL) layer (i.e. the hexagon) depends on the persistence layer (the objects that access the db). So that the BL is tied to the db, the ORM or whatever framework or technology you use to persist the data. If you change anything related to the db, it will affect to your BL.

      In hexagonal architecture, the dependency is the other way: the persistence logic (driven adapter) depends on the BL (hexagon), so that your business doesn’t depend on storage technology, it is agnostic about the db. If you change db it doesn’t imply changes on your BL.

      How to achieve this? With an abstraction (interface): your BL doesn’t care about “how” (implementation) the persistence of an object is made, so it just have an interface saying “store object”, “retrieve object”, etc (in the language of the BL, not in the language of the db). This interface belongs to the BL, while the implementation belongs to the adapter. So driven adapter depends on the BL.

      In classic layered architecture, that abstraction (interface) doesn’t exists (or if it exists, it belongs to the persistence (secondary adapter). So the dependency is: BL depends on driven adapter.

      Like

  9. Hi Juan,
    great article, it’s one of the most clear I’ve found on this topic.
    I have one question:
    Why I need interfaces also on the left side of the exagon?
    Their purpose is to abstract the funcionality of the domain.
    I agree that is useful to abstract the right side because in this way I can easly replace providers (or mock them). But what’s the point of abstract the domain?
    I suppose the the domain is only one so I don’t need switch to another. Moreover, I think it’s not particularly useful to test the driver adapters (e.g. Web API controller) while mocking the domain. So why abstract it? Is it only to mantain simmetry between left and right side or are there practical reasons?
    The more I think about it, the more seems to me a useless new level of indirection.
    Suppose I’ve implemented the app layer inside the hexagon (which I consider part of the domain in this case) following the Command pattern, creating one class for each use case.
    In this way I don’t even need to use interfaces to segregate driver ports for each adapter (they are all sergragated alerady by the implementations).
    Thanks in advance.
    Filippo

    Like

    1. Hi Filippo,

      thank you very much, I’m glad you like the article. Sorry for the delay answering.

      I assume that when you say domain you mean “application” (hexagon). Don’t confuse “application” in the Hexagonal Architecture terminology with “application” in DDD terminology (applicationOfHA = applicationOfDDD + domainOfDDD)

      Well, driver ports are the API of the application (hexagon), and usually an API are interfaces. Using interfaces is a good practice when designing an API. Even the acronym says it is an interface (Application Programming Interface):

      – Interfaces helps to achieve the Information Hiding Principle, since you keep the implementation in a class behind the interface.

      – Interfaces let you achieve the D principle of SOLID. Dependencies should be on abstractions, not concretions.

      – Interaces decouple the API consumer (the driver adapter) from the API provider (the hexagon). You wouldn’t have a completely decoupled architecture if driver ports weren’t interfaces.

      – Interfaces are abstractions, they define what the functionality does, not how it is done. An API defines contracts, which are abstractions, not implementations.

      – Interfaces allows you hardcoding the hexagon and test a driver adapter, if you want to have a fully testable architecture. They are integration tests. Why isn’t it useful? It helps you to localize errors.

      Following the command pattern, the driver port is still an interface. Just one interface (the command bus). Then for each use case you have: a command (DTO with the data that the use case accept as arguments) and a command handler (class with the use case implementation). If you are implementing DDD, all of this components of the command pattern belongs to the application layer, but the port is just the command bus interface. Inside the hexagon you would have the application layer and the domain.

      Hope my answer helps.

      Regards,
      Juan.

      Like

      1. Hi Juan, thank you for the feedback.
        I agree on all you wrote, your approach is surely the most correct. My doubt was only about the case when you know you will ever have only one implementation of the applicationOfHA.
        Confrontation always helps!
        Regards
        Filippo

        Like

        1. Hi Filippo,

          no confrontation at all. I know what you mean. But even in that case, I prefer to put the API apart in a interface. Don’t like to mix API and implementation in one class. But I know the case you mention, it is like having an interface with just a (default) implementation. Vaughn Vernon talks about it in his book IDDD in the application services chapter, and also the book Java 9 Modularity by Sander Mark, which is quite a good book. But you know, I prefer interface apart, it is more clear.

          Thanks for your comments.

          Regards,
          Juan.

          Like

          1. Sorry for my english, I meant “comparison”.
            Thaks for bibliographic references.
            Filippo

            Like

  10. Thanks for the clear and great article.

    Now, how does one convince people at work not to “marry the frameworks”? For example in the beginning of (new) project spring boot with db-driven design seems fine. But then more and more stuff gets added resulting in big ball of mud

    Like

    1. Hi Tapio,

      thanks for your words and for the question. I’m not very good at convincing people, I ended up discovering hexagonal architecture on my own, because as you have said, in a large project there was a moment when I looked at the code and didn’t know what it was doing, it was a nightmare of framework annotations.

      Spring boot is good, I use it too, the point is don’t let it leak into the business logic (application, hexagon). Tell the people that just adapters and composition root are allowed to marry spring boot. Even doing so, hexagonal architecture doesn’t save you from a big ball of mud on each component of the architecture. The point is to structure the code of each one.

      Reasons for convincing people not to use frameworks at the business logic are those I mention in the article (you know, testability, maintainability, etc), but the art of making people follow you is a thing in which I’m afraid I cannot help you.

      Thank you very much for reading, and sorry for my delay answering.

      Regards,
      Juan

      Like

  11. Hola Juan
    Thanks for the reply. Asking advice how to convince people was more or less theoretical question =) Still I would appreciate if you could elanorate some points
    1. What does “composite root” mean? Aggregate root? The main class (by uncle bob) or something else?
    2. About the transactions with commands and decorators. I’m missing something here. Lets say we have usecase to create new Foobar and to save it. Now we could have driven port ISaveFoobar which would be implemented with Spring service (marked with @Transactional) basically just wrapping spring repository FoobarRepository. Or is it that then implementation would be still coupled with how spring manages transactions? E.g. we need more ecplicit way of telling about need of transactions.
    3. Still regarding transactions. How about situation where we need to not only persist changes inside transaction but also the “reading” parts should happen also inside single atomic transaction. I mean that in typical spring app we could have service marked @Transactional whose method could read from multiple repositories and then based on that info persist some changes. All taking place inside one TX

    Thanks in advance!

    Like

    1. Hola Tapio, sorry for the delaying, to your questions:

      (1) Composition Root definition: https://blog.ploeh.dk/2011/07/28/CompositionRoot/
      Basically, it is the component that composes all the modules together at startup.
      Rbert C. Martin names it “the main component” in his book “Clean Architecture”.
      For hexagonal architecture, I drew this pic at twitter: https://twitter.com/TotherAlistair/status/1122918489558278145 , and I named it “dependency configurator”.
      No matter how you call it, the point is that it builds the whole system and run it.
      It is important to remark that it isn’t a component defined in the pattern.
      I’ve researched several ways to implement it, but the easiest is the one I explain in the article (section 2.5).
      Hope some day I will write an article with the different approaches I’ve been studying.

      (2) & (3): For transactions, I wrap every use case (driver port) call, with a “transactional service” interface (driven port). This driven port is implemented by an adapter which has the spring @Transactional. It wraps not just one repository, but the whole use case code, that can involve multiple repositories.
      I have an example where I use a command/query mediator as the only driver port of the application, and a transactional decorator which calls the transactional driven port. If you are interested, I can send you by email.

      Thank you for reading.
      Juan.

      Like

  12. Hi Juan and thanks for replying! I would love to see the example of how to manage transactions (so please send it as email =) ) However Im pretty sure someone else would like to see that example as well, so maybe even own article/github link?

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s