A stack of bright blue and pink cubes against a dark background.

DDD architectures in comparison

Estimated reading time: 6 minutes

HomeKnow-HowDDD architectures
Author: Stephan Schneider
Author: Stephan Schneider

DDD Architectures: Onion Architecture and Ports and Adapters Style — A Comparison

In his book Domain-Driven Design: Tackling Complexity in the Heart of Software (2003), Eric Evans presented the tactical patterns of DDD (repository, value object, etc.) without showing how they could be implemented in software architecture.
 
Ten years later, in the foreword to Vaughn Vernon's book ‘Implementing Domain-Driven Design’ (2013), Evans at least noted that Alistair Cockburn's Ports and Adapters (the ‘Hexagonal Architecture’) is better suited to DDD than layer architecture.

 An abstract illustration shows a human figure made up of geometric shapes in a pattern of pink and purple.
… hexagonal architecture, which has emerged as a better description of what we do than the layered architecture.
Eric Evans

However, Vernon himself consistently uses terms from Jeffrey Palermo's onion architecture in his book. This raises the question of whether this is the same architectural style.

I explore this question in this blog article: I compare the basic concepts of the Ports and Adapters and Onion Architecture models. As a third model, I take a look at Robert Martin's Clean Architecture. In conclusion, I summarise the advantages of the three models.

Ports and adapters or ‘hexagonal architecture’

With his Ports and Adapters architecture (2005), Alistair Cockburn places the technical aspects of an application at the centre of software design for the first time, thereby relegating the database to an implementation detail. He places the logic layer of the layer model (see diagram) at the centre and calls it Core Logic (see diagram). He calls the outer layers (presentation and data) adapters and decouples them from the core logic by means of an additional layer, the ports. He calls a port driven by the front end and its adapter primary and a port driving the database and its adapter secondary.

 A diagram shows the structure of a software architecture, consisting of presentation, logic, data, core logic, adapters and ports.
This is how the layers of a layer architecture are mapped to ports and adapters.
Layered ArchitecturePorts and Adapters
PresentationPrimary Adapters
Primary Ports
LogicCore Logic
Secondary Ports
DataSecondary Adapters

Ports and Adapters — Core Logic

Evans' repository interface and its implementation (e.g. a database connection) can be located in the secondary port and its adapter. However, other tactical patterns of DDD belong in the core logic, without Evans or Vernon providing any information on how this should be divided. Another layer consisting of primary and secondary ‘core services’ surrounding the ‘model’ would be conceivable (see diagrams on the left and right). In this scenario, the secondary core services would aggregate the data provided via the secondary port (e.g. events) into the model. Both the model and the secondary core services would then be available to the primary core services to map the API offered in the primary port (e.g. commands and queries) to the use cases of the application.

 A diagram illustrates a software architecture with a model, core services, ports and adapters.
The core logic behind ports and adapters

Onion Architecture

In 2008, Jeffrey Palermo presented his Onion Architecture, also as an improvement on the layer model — incidentally, without reference to Cockburn's Ports and Adapters. Looking back, however, Cockburn's Core Logic can be found in Palermo's architecture as the Application Core (see left graphic). Similar to Cockburn's hypothetical Core Logic (see graphic on the right), this is subdivided into two further layers (Application Services and Domain Services, collectively referred to as Business Logic) with the Domain Model in the middle. However, Palermo does not divide his Business Logic into primary and secondary, but arranges it concentrically.

 A diagram shows the architecture of the application core and core logic with categories such as model, domain server and core services.
Comparison: the application core of the onion architecture (left) and core services in ports and adapters (right)
Onion Architecture
(Application Core)
Ports and Adapters
(Core Logic)
Application ServicesPrimary „Core Services“
Domain Model„Model“
Domain ServicesSecondary „Core Services“

This shows that in Palermo, domain services are located between application services and the domain model. Fortunately, application services can still access the domain model directly, because layers can be skipped in Palermo.

Eine abstrakte Illustration zeigt eine menschliche Figur aus geometrischen Formen in einem Schema aus Rosa und Violett.
With traditionally layered architecture, a layer can only call the layer directly beneath it. This is one of the key points that makes Onion Architecture different from traditional layered architecture.
Jeffrey Palermo

In fact, every outer layer can access every inner layer, which is why you won't find anything in Palermo that corresponds to Cockburn's ports, which would isolate the application core. Consequently, tests of any granularity can be placed outside the application core (see diagram on the left), together with the user interface and infrastructure, which correspond to Cockburn's primary and secondary adapters. As a result, inner layers, including the domain model, can be coupled with outer layers, even with the infrastructure or the user interface (see graphic on the right).

 A diagram describes the software architecture with domain model, application services, user interface, tests and infrastructure.
Onion architecture: concentric or not?

Clean Architecture

In his Clean Architecture (2012), Robert C. Martin (‘Uncle Bob’) refers to Palermo's business logic as business rules and divides them into application-specific and enterprise-wide (corresponding to Palermo's application services and domain services), but without an explicit logic core that would correspond to Palermo's domain model (see diagram). Accordingly, Martin's enterprise-wide business rules include value objects (business objects) as well as entities and repository interfaces. Application-specific business rules include use cases (or use case interactors) and DTOs (request model and response model). The latter are used or implemented by controllers and presenters in the next outer layer, the interface adapters. The outermost layer contains the framework drivers, which implement the repository interfaces of the enterprise-wide business rules, for example. As with Palermo, dependencies can point as deep as desired into the application. Martin calls this architectural freedom the dependency rule and also allows any number of additional layers.

Eine abstrakte Illustration zeigt eine menschliche Figur aus geometrischen Formen in einem Schema aus Rosa und Violett.
The overriding rule that makes this architecture work is The Dependency Rule. This rule says that source code dependencies can only point inwards.
Robert C. Martin
 The diagram illustrates company-wide and application-specific business rules with interface adapters and dependency rules.
Clean Architecture according to Uncle Bob (Robert C. Martin)

Conclusion: Best of DDD Architecture

Now that we have compared the three best-known ‘DDD architectures’ that focus on technical expertise — ports and adapters, onion architecture, and clean architecture — it should be clear that although they are very similar, they cannot be treated as synonymous: Cockburn has no equivalent to Palermo's business logic or Martin's business rules, while Palermo and Martin have abandoned Cockburn's concept of ports (in favour of the dependency rule). An architecture combining decoupling ports, as in Cockburn, with business logic, as in Palermo, which can be used to implement the tactical patterns of DDD, is therefore my personal ‘best of DDD architecture’. In this context, it seems sensible to me to divide the architecture into driving and driven halves, i.e. into program adapters, ports and services as well as language adapters, ports and services, in order to clearly position the application between the front end and the (DB) back end.

If ports are viewed as service interfaces, ports and services can be grouped together as program and language. To avoid program adapters and language adapters being mistakenly understood as part of this new program layer or language layer, I prefer the designators presentation and interpretation.

 The diagram shows the software architecture with the domain at its core, surrounded by presentation, program, language and interpretation.
Best of DDD Architecture: Presentation/Program/Domain/Language/Interpretation und Services, Ports and Adapters

With this in mind: Happy DDD-ing!

„Best of DDD Architecture“Ports and AdaptersOnion ArchitectureLayered Architecture
Presentation (Program Adapters)Primary AdaptersUser InterfacePresentation
Program PortsPrimary Ports
Program ServicesCore Logic (Primary „Core Services“)Application ServicesLogic
DomainDomain ModelApplication ServicesLogic
Language ServicesCore Logic (Secondary „Core Services“)

Domain Services

Logic
Language PortsSecondary Ports

Interpretation
(Language Adapters)
Secondary Adapters

Infrastructure

Data

Literature
  • [Eva03] Evans, Eric, Domain-Driven Design: Tackling Complexity in the Heart of Software, Addison-Wesley, 2003
  • [Ver13] Vernon, Vaughn: Implementing Domain-Driven Design, Addison-Wesley, 2013
Author: Stephan Schneider
Author: Stephan Schneider

Stephan Schneider is Lead Software Engineer at MaibornWolff. He is passionate about human-readable code in testing and production. His goal is to make the translation of requirements into features as sustainable and comprehensible as possible. He is therefore passionate about modern programming languages such as Kotlin, which support functional programming concepts without a lot of boilerplate or design patterns, as well as software architectures that cleanly separate technical and business aspects. Even under feature pressure, testability and maintainability must be preserved.

Find what suits you best
Refine your search
clear all filters