Ports and adapters / hexagonal architecture - clarification of terms and implementation

后端 未结 4 492
一个人的身影
一个人的身影 2021-01-30 04:31

After reading different sources about the Ports & Adapters architecture including Alistair Cockburn\'s original article I am still not sure about the definite meaning of the

相关标签:
4条回答
  • 2021-01-30 04:53

    inf3rno gave a good answer which clarifies the original question, but it may be useful to highlight some other uses for ports and adapters.

    According to my understanding the port is an expression of your interface.

    The port:

    • Defines the exposure of the core's functionality (for 'incoming' ports)
    • Defines the core's view of the outside world (for 'outgoing' ports)

    The adapter:

    • Is located outside the component (hexagon)
    • Is used to ensure that the transport between port and the target happens in a way that satisfies the contract with the port's interface
    • Is what you replace (using dependency injection) to test the hexagon

    The port should accept the adapter and make sure that the adapter implements the interface. Then it should merely call the appropriate methods/functions on the adapter.

    The port should be included in communication testing. In that case, what is 'mocked out' is the cores of two neighbouring hexagons (or a hexagon and a service) and test the port/adapter/adapter/port assembly.

    For more information you can view the talk about Hexagonal Microservices that James Gardner and I gave at London's Skillsmatter Microservices meetup in July 2014.

    0 讨论(0)
  • 2021-01-30 04:53

    Someone at my work did a great internal presentation on this architecture. At the end, during question time, another colleague asked:

    Isn't this just a layered architecture with a different name and drawn differently?

    And, to be honest, that's true to a large extent. For many applications, a hexagonal architecture will be structured identically to a layered architecture, with a few specific details:

    • There is increased discipline in defining interfaces between each layer (the ports), rather than calling impl to impl.
    • There is a focus on "the core" (business logic) as being the most important layer, with all other layers (the adapters) being viewed as somewhat subservient.
    • The focus on defining interfaces from the perspective of the core prevents the language of the adapters from leaking into the core. For example, if you're putting your persistence (e.g. Hibernate) into an adapter, then you should not have any @Entity classes in your core.

    You can see that, even when doing all these things, it's still just a layered architecture, just with the boundaries between layers being quite strict and a focus on the central layer.

    So, to specifically answer the question, you can understand ports and adapaters by recognising that ports are the interfaces into and out of the core, and adapters are just the implementation layers that are not the core.

    0 讨论(0)
  • 2021-01-30 04:57

    I think it is pretty simple concept. You have the application core, which does not depend on anything outside of it. For example it does not depend on HTTP frameworks, database drivers, mailing frameworks, and so on... This core has a very specific interface depending on your problem domain, so the code of your application core should change only if your problem domain changes.

    For example you have blog posts and you want to add categories to them. So the categories should flow through the entire system, from the HTTP communication to the databases by writing and vice-versa by reading.

    Now what if you want to replace your MySQL database for example with MongoDB, because why not. It should not affect the core, because the application does still the exact same thing: it stores your blog posts and ofc. their categories and returns them on demand. So what you need is only a MondogDB adapter in this case, which you can use instead of your MySQL adapter.

    What if you want for example a REST API, and not just a simple HTML page? It still does not affect your application core, so what you need is another adapter for REST communication.

    So in my opinion your adapters should have specific interfaces defined in your application core, and the ports should communicate with the application core using these adapters. So in my opinion the ports do not necessary exist as classes, just the adapters, and their interface. This concept makes sense, because your application core won't be tightly coupled to the ports you want to use, just to the adapter interfaces you define. (There are multiple similar architectures by the way. Like clean architecture, onion architecture, which use the same concept with a different vocabulary.)

    0 讨论(0)
  • 2021-01-30 04:59

    From my point of view, after reading the original article and watch some talks by Alistair Cockurn ("Alistair in the Hexagone"), I think the correct approach is what you would call "all inside", i.e. in both inbound and outbound communication, the ports are "inside" the adapters. The adapters are between the external actors that interact with the app, and the the ports. Ports belong to the app.

    For inbound communication, the actor (driver actor) triggers the communication using a driver adapter. This adapter calls a driver port of the app, requesting the app to do something.

    For outbound communication, the app triggers the communication with a driven actor by defining and calling a driven port. This port is a contract (usually an interface) of what the app needs in terms of the purpose. This port is implemented by an adapter, that communicates with the external actor.

    Dependencies should be:

    Driver Actor --> Driver Adapter --> Hexagon <-- Driven Adapter <-- Driven Actor

    Ports belongs to the Hexagon:

    Driver Ports are the API offered by the Hexagon to Driver Adapters.

    Driven Ports are the SPI needed by the Hexagon, implemented by Driven Adapters.

    I struggled a lot too with this sentence you mention, which appear in the original article:

    "As events arrive from the outside world at a port, a technology-specific adapter converts it into a usable procedure call or message and passes it to the application."

    It is saying that driver ports are "outside" driver adapters. But reading the whole article and watching the talks, I think that it isn't that way. What the sentence calls "port", is simply the interaction between the external driver actor and the adapter. The "port" should be the interaction between the adapter and the app ("...passes it to the application").

    0 讨论(0)
提交回复
热议问题