29

So, in the hexagonal architecture layer, the application layer has incoming ports (use cases) that are called from incoming adapters, implemented by services, that use outcoming ports that are implemented by outgoing adapters.

Is it really different than the layered architecture? Other than calling outcoming adapters as DAO? And some kind of pretty package structuring? We have services as well implemented by interfaces.

  • So am I doing hexagonal without knowing?

  • In other words, what problem does hexagonal architecture solve, that a layered architecture doesn't?

Rohit Gupta
  • 203
  • 2
  • 3
  • 12
codemonkey
  • 401
  • 1
  • 4
  • 7
  • 8
    "Layered" is very general - almost any architecture is layered, including hexagonal architecture (they just draw the layers more like onion layers than a layer-cake, but this is rather arbitrary). But many traditional layered architectures consider the database the lowest/innermost layer, whereas hexagonal consider the domain model the innermost layer. So this is a shift of perspective. – JacquesB Jan 23 '22 at 13:10
  • 2
    Putting the domain model at the center of the architecture is not just enforced by hexagonal architecture. Onion architecture also does this. – Greg Burghardt Jan 23 '22 at 13:12

5 Answers5

20

The key difference is about dependency management:

Layered architectures are intended to reduce dependencies by stacking layers: every component in one layer may depend on components of the layer below (in principle, immediately below, although "open layers" can be bypassed). There are many variants, but for example:

                             dependency
Presentation (UI)                |
Services                         |
Data access layer (DAL)          |
Database                         V 

Hexagonal architecture (and subsequently Onion or Clean architectures as well) use dependency inversion. In this architecture, the outer cores shall only be dependent on inner cores. But dependency inversion is used to allow the inner cores to use abstract interchangeable interfaces without knowing their specific implementations.

                                      dependency  dependency inversion
Interfaces (to DB, with user, ...)        |        <--+
Services                                  |           |
Business logic                            |           |
Entities                                  V        ---+

When the layers/cores represent an internal decomposition in your system, the hexagonal approach allows you to have more abstract elements at the center, and build concrete classes on abstractions, whereas the layers require you to depend on concrete implementations.

Some more thoughts:

  • when layers become tiers, i.e. deployable components that could run on different servers, a careful API design may sufficiently decouple the abstractions between each of the layers, to make the difference less obvious

  • layers are more difficult to split horizontally, whereas in the hexagonal approach, it's easy to rely on abstractions whose implementations are outsourced via a port and a connector to another hexagon (that's the idea behind the microservice architecture)

psmears
  • 188
  • 4
Christophe
  • 74,672
  • 10
  • 115
  • 187
  • 1
    Could you give *concrete examples* of hexagonal architectures? What should be needed in the [RefPerSys](http://refpersys.org/) project or the [Frama-C](https://frama-c.com/) to make its architecture "hexagonal"? Feel free to email me (to `basile@starynkevitch.net` at home), or to `basile.starynkevitch@cea.fr` at office, working at https://www-list.cea.fr/ – Basile Starynkevitch Jan 30 '22 at 15:03
  • 1
    @BasileStarynkevitch basically most microservice based systems rely on an hexagonal architecture or a derivatives. But why are you looking for examples? What makes you think your systems should use hexagonal architecture, and what makes you think that they currently are not? – Christophe Jan 30 '22 at 16:27
  • @BasileStarynkevitch (Sorry if do not reach out for your private email: I have a full-time job and am here in my free time for contributing to the public knowledge. I therefore have no interest in starting private email discussions, even if in my youth I've read "Metaconnaissances" and was fascinated by the ideas behind your RefPersys. Moreover, 89Mb for one repository and 1,5 Mb for the other would require too much of my time to provide you a meaningful answer. If you can formulate a specific question, don't hesitate to post it on SE). – Christophe Jan 30 '22 at 16:29
  • It is the first time I read about "hexagonal" architectures (software)? Did you heard of / can you give example of "square" architectures, "triangular" ones, "spherical" ones (in software architecture)? – Basile Starynkevitch Jan 30 '22 at 17:24
  • Has the [GCC](http://gcc.gnu.org/) compiler some "hexagonal" architecture? – Basile Starynkevitch Jan 31 '22 at 10:10
  • Does the [Linux kernel](https://kernel.org/) has in 2022 some "hexagonal" architecture? – Basile Starynkevitch Jan 31 '22 at 11:51
  • @BasileStarynkevitch Not sure how your question is related to my answer: 1) hexagonal architecture makes sense essentially for OOP, since it's more difficult to inject dependencies in non-OOP. 2) I don't think hexagonal app architecture is suitable for OS. Even minix with its micro-kernel is layered. 3) If I look at [GCC internal overview](https://en.m.wikibooks.org/wiki/GNU_C_Compiler_Internals/GNU_C_Compiler_Architecture) I seem to recognize a [classical pipes and filter](https://syedhasan010.medium.com/pipe-and-filter-architecture-bd7babdb908) architecture. – Christophe Jan 31 '22 at 12:37
  • 1
    @BasileStarynkevitch Hexagonal Architecture is in fact the nick name of "Ports and adapter" architecture from Alister Cockburn https://alistair.cockburn.us/hexagonal-architecture/ The name "haxegonal" comes from the shape of the illustrations but has nothing to do with something 6-ish. – JayZ Jan 13 '23 at 10:03
17

It can be confusing, with Layered Architecture being such generic term. Nowadays, anything is layered architecture. Difference is what each layer does and how they depend on each other.

(Legacy) Layered Architecture or Three-tier achitecture consists of layers. On to bottom is database /persistence layer, where data is persisted. On top is business layer, where all the interesting domain logic happens. And on top of that is presentation layer. The most important thing to notice is that business layer depends on persistence layer. This means that you cannot use business objects without also dragging in persistence. Usually in form of database.

Hexagonal, Clean and Onion architectures also have layers. But the difference between these and the (legacy) layered architecture is that it puts the business domain at the bottom/center. This means that business model and domain entities are independent of their persistence. This is really helpful for testing, as you don't need to bother to spin up the database. And is agnostic to persistence, so you can use SQL, NoSQL, etc... and you domain entities shouldn't care about what database you use.

Euphoric
  • 36,735
  • 6
  • 78
  • 110
  • 1
    Ok, but I think in a layered architecture, the domain entities can be agnostic too, for instance, Let's say I may decide to use for instance mongoDAO, insetead of MySQL dao, and it would not be so "dependent" on it, i would just change "a line", like the one with hexagonal. – codemonkey Jan 23 '22 at 13:31
  • @codemonkey There's a difference in *where* you change that line of code. In a layered architecture, you change your business layer. In a hexagonal architecture (ports and adapters), you leave your core application completely unchanged and instead swap the database-specific adapter, so basically architecture-level dependency injection. Personally, I think that ports & adapters is overkill and layers are perfectly fine for a lot of software, like smallish CRUD apps. But ideas like DDD, microservices, and onion architectures clearly have a lot of appeal in larger and more enterprisey software. – amon Jan 23 '22 at 14:20
  • 1
    @amon Personally I've never once seen a layered architecture that could actually replace its database layer with a different technology after the fact without large amounts of effort and refactoring. Turns out having a direct reference to the DB specific code (even if there are interfaces and whatnot involved) virtually guarantees that someone is going to rely on a leaky abstraction. But yeah might be doable for small applications with maybe 100k LOC. – Voo Jan 24 '22 at 10:40
7

Layered is usually like this (arrow indicates a dependency):

Data <-- UI

Which split apart a bit more can become:

Data <-- Logic <-- UI

Hexagonal uses dependency inversion to achieve:

Data --> Logic <-- UI

And further:

 Database -->  |-------|  <-- CLI
Resources -->  | Logic |  <-- Desktop GUI
    Files -->  |-------|  <-- Web UI

The modules on the left are called "driven" and simply respond to requests. The modules on the right are called "drivers" and are where requests are generated. Everything goes through the Logic which is the business rules of the system written in pure dependency-free code. The Logic becomes the language of the system that any of the parts can use to communicate with the other parts.

This sounds amazing, and it is, though it can be a bit more tricky to implement than this sounds. But at the same time, I find everything has a tendency to fall into place; everything has a clear place to live.

In the Data <-- Logic <-- UI setup, I found that the code in "Logic" never made sense to put anywhere in particular. It could go in any of the three places and still never felt right. This is because it was still really database code, and since the UI knew about the database, database code could still go right in the UI. Or it could go in the Data layer. Or it could go in the "Logic" layer.

With Hexagonal, all dependency is filtered out of your Logic like a sieve, leaving only pristine dependency-free Logic code left over. You now want to put as much code as you can in the Logic module, because just by putting it there you remove its dependencies and make it more reusable.

Dave Cousineau
  • 313
  • 3
  • 10
5

Remember that software is built from code, not diagrams. Certainly both architectural views have been employed in working software, so it is not that one isn't useable, just that the maintainability is different.

In layered architecture, the UI is the first interaction point and triggers processes in the Service layer, which gets its data from the database (layer). However, these interaction points are hardwired, the API of the database layer is defined by the database needs and a change in deeper layers often requires changes in upper layers, e.g., the UI integration.

In hexagonal architecture, the business logic is at the center, and it just uses an database adapter that was provided at the start and conforms to the API (= port) that the business layer expects to do its job - and if the some service is not conforming to the business API, it is adapted to that interface.

However, this is the static architectural view. In the end, both architectures produce a very similar call stack during run time. The UI still is the first interaction point, an event triggers processes through the input port of the business API, which further calls a database adapter... because the user experience and end results should be the same.

1

I am under the impression that the only difference between layered and hexagonal is the fact that hexagonal forces you to always depend on interfaces instead of implementations, which is widely considered a best practice regardless of the architecture. In my experience I have always used what I thought to be layered architecture, but by always coding to interfaces, I was probably using hexagonal...

I would say hexagonal is different way of describing the layered architecture that suits well with DDD and Microservices, but in the end, both architectures will essentially produce the same code and call stack: Controller -> Service -> Repository

IonutB
  • 19
  • 2