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

 

Advertisements

29 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. 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

  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

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