Understanding the concept of Hexagonal Ports and Adapters with an example

I am trying to understand what is meant by a Port and an adapter when talking about Hexagonal architectures. I have read plenty of explanations tonight, however I have not found a code example. Therefore I will devise one. I understand a port to be an interface. For example:

public interface IPerson
{
   string GetName();
}

and an Adapter to be a class that implements an interface:

public class Person : IPerson
{
  //Implementation of GetName here
}

I understand the concept of the Gang of four Adapter pattern. However, I do not understand how this fits into DDD.

It would really help me to see a simple code example in the context of DDD.

2 answers

  • answered 2018-10-12 01:46 choquero70

    an Adapter to be a class that implements an interface

    Not always. That's true for the driven side, but for the driver side, an adapter is a software component that uses the interface (calls its methods).

    I've written a conceptual article about Ports and Adapter Pattern (Hexagonal Architecture):

    https://softwarecampament.wordpress.com/portsadapters

    There you can read about it.

    I have read plenty of explanations tonight, however I have not found a code example.

    Some code I've just invented, to explain to you what a port and what an adapter are in practice:

    In an online shop, a driver port could be:

        public interface ForManagingShoppingCart {
            public void addProductToShoppingCart ( String productId );
            // ... more methods ...
        }
    

    A driver adapter could be a controller, that takes user requests from the UI and calls the methods of the driver port:

        public class ShoppingCartController {
    
            private final ForManagingShoppingCart forManagingShoppingCart;
    
            // Injects port in the constructor
            public ShoppingCartController ( ForManagingShoppingCart forManagingShoppingCart ) {
                this.forManagingShoppingCart = forManagingShoppingCart;
            }
    
            // Method that executes when user selects a product in the view and clicks the "add product" button
            public void addProductOnClick ( String productId ) {
                this.forManagingShoppingCart.addProductToShoppingCart ( productId );
            }
    
        }
    

    If the application sends you an email when you do a purchase order, a driven port could be:

        public interface ForNotifyingClients {
    
            public void sendPurchaseOrderConfirmation ( String recipient );
    
        }
    

    The port is technology agnostic, it doesn't know if the message is sent by email. The driven adapter implements the port using an email system.

    I understand the concept of the Gang of four Adapter pattern.

    The adapter pattern fits because you are translating the port interface methods into email system interface methods.

        public class EmailNotificationAdapter implements ForNotifyingClients {
    
            private final EmailSystem emailSystem;
    
            // Inject the email system interface you want to use in the adapter constructor
            public EmailNotificationAdapter ( EmailSystem emailSystem ) {
                this.emailSystem = emailSystem;
            }
    
            // Implements the method using the email system to send an email
            @Override
            public void sendPurchaseOrderConfirmation ( String recipient ) {
                // ...code that sends an email to the recipient using this.emailSystem
            }
    
        }
    

    I do not understand how this fits into DDD... It would really help me to see a simple code example in the context of DDD.

    DDD fits well into Hexagonal Architecture:

    • Application Layer and Domain Model would be inside the hexagon.
    • Application Services API would be the driver ports of the hexagon.
    • Presentation Layer (UI) would be a driver adapter.
    • Infraestructure Layer would contain the driven adapters.
    • When the application layer or the domain model need to deal with technology, they define a driven port, that a driven adapter in the infraestructure would implement.

  • answered 2018-10-12 02:00 VoiceOfUnreason

    TLDR: ports and adapters isn't like usb plugs and usb sockets. Adapters are USB to Lightning cables.

    I am trying to understand what is meant by a Port and an adapter when talking about Hexagonal architectures.

    It's a bit of a tangle, especially because

    1. The pictures alone don't tell the story
    2. The pictures look a lot like the onion, and tell the story a different way.

    The two nested polygons (traditionally, two hexagons) represent logical boundaries. The "core domain logic lives entirely within the inner polygon. Outside of the outer polygon is the real world: message buses, databases, UI, file systems, and so on. All of these things have ports.

    For example, in the interactive shell, your ports are stdin, stdout, stderr.

    The adapters are the things we put in place because the ports at the outer boundary and the ports at the inner boundary don't match. My domain model doesn't speak SQL, so I have an adapter that sits between my domain model and my database client. My domain model doesn't understand terminal formatting, so I have an adapter that sits between the domain model and the interactive shell.

    Part of the magic here being that we can bring new components together by changing the adapter. My domain logic doesn't know about HTML presentation either, but I should be able to replace the interactive shell adapter with a web browser adapter, and give users a new way to interact with the domain model. I should be able to switch out persistence strategies by using a new adapter to communicate with a new stable storage appliance.

    Ports are commonly going to be interfaces, because what we care about at the boundary is clearly defining the contract that needs to be satisfied, without coupling to a specific implementation.

    I do not understand how this fits into DDD.

    One reason that it is hard to see how this fits; ports and adapters is plumbing, not domain model. All the bits that justify the work of doing domain analysis lives inside the inner polygon.

    Repositories and Domain Services are common forms of adapters. Domain Services are commonly ports, with the implementation provided by the application or infrastructure components. Similarly, repositories are typically a form of adapter between the application and the stored collection of aggregates.

    Recommended Reading: * Ports and Adapters Architecture @c2 wiki