This post is part of The Software Architecture Chronicles, a series of posts about Software Architecture. In them, I write about what I’ve learned on Software Architecture, how I think of it, and how I use that knowledge. The contents of this post might make more sense if you read the previous posts in this series.
Robert C. Martin (AKA Uncle Bob) published his ideas about Clean Architecture back in 2012, in a post on his blog, and lectured about it at a few conferences.
The Clean Architecture leverages well-known and not so well-known concepts, rules, and patterns, explaining how to fit them together, to propose a standardised way of building applications.
Standing on the shoulders of EBI, Hexagonal and Onion Architectures
The core objectives behind Clean Architecture are the same as for Ports & Adapters (Hexagonal) and Onion Architectures:
- Independence of tools;
- Independence of delivery mechanisms;
- Testability in isolation.
In the post about Clean Architecture was published, this was the diagram used to explain the global idea:
As Uncle Bob himself says in his post, the diagram above is an attempt at integrating the most recent architecture ideas into a single actionable idea.
Let’s compare the Clean Architecture diagram with the diagrams used to explain Hexagonal Architecture and Onion Architecture, and see where they coincide:
Externalisation of tools and delivery mechanisms
Hexagonal Architecture focuses on externalising the tools and the delivery mechanisms from the application, using interfaces (ports) and adapters. This is also one of the core fundaments of Onion Architecture, as we can see by its diagram, the UI, the infrastructure and the tests are all in the outermost layer of the diagram. The Clean Architecture has exactly the same characteristic, having the UI, the web, the DB, etc, in the outermost layer. In the end, all application core code is framework/library independent.
In the Hexagonal Architecture, we don’t have anything explicitly telling us the direction of the dependencies. Nevertheless, we can easily infer it: The Application has a port (an interface) which must be implemented or used by an adapter. So the Adapter depends on the interface, it depends on the application which is in the centre. What is outside depends on what is inside, the direction of the dependencies is towards the centre. In the Onion Architecture diagram, we also don’t have anything explicitly telling us the dependencies direction, however, in his second post, Jeffrey Palermo states very clearly that all dependencies are toward the centre. The Clean Architecture diagram, in turn, it’s quite explicit in pointing out that the dependencies direction is towards the centre. They all introduce the Dependency Inversion Principle at the architectural level. Nothing in an inner circle can know anything at all about something in an outer circle. Furthermore, when we pass data across a boundary, it is always in the form that is most convenient for the inner circle.
The Hexagonal Architecture diagram only shows us two layers: Inside of the application and outside of the application. The Onion Architecture, on the other hand, brings to the mix the application layers identified by DDD: Application Services holding the use case logic; Domain Services encapsulating domain logic that does not belong in Entities nor Value Objects; and the Entities, Value Objects, etc.. When compared to the Onion Architecture, the Clean Architecture maintains the Application Services layer (Use Cases) and the Entities layer but it seems to forget about the Domain Services layer. However, reading Uncle Bob post we realise that he considers an Entity not only as and Entity in the DDD sense but as any Domain object: “An entity can be an object with methods, or it can be a set of data structures and functions.“. In reality, he merged those 2 innermost layers to simplify the diagram.
Testability in isolation
In all three Architecture styles the rules they abide by provide them with insulation of the application and domain logic. This means that in all cases we can simply mock the external tools and delivery mechanisms and test the application code in insulation, without using any DB nor HTTP requests.
As we can see, Clean Architecture incorporates the rules of Hexagonal Architecture and Onion Architecture. So far, the Clean Architecture does not add anything new to the equation. However, in the bottom right corner of the Clean Architecture diagram, we can see a small extra diagram…
Standing on the shoulders of MVC and EBI
The small extra diagram in the bottom right corner of the Clean Architecture diagram explains how the flow of control works. That small diagram does not give us much information, but the blog post explanations and the conference lectures given by Robert C. Martin expand on the subject.
In the diagram above, on the left side, we have the View and the Controller of MVC. Everything inside/between the black double lines represents the Model in MVC. That Model also represents the EBI Architecture (we can clearly see the Boundaries, the Interactor and the Entities), the “Application” in Hexagonal Architecture, the “Application Core” in the Onion Architecture, and the “Entities” and “Use Cases” layers in the Clean Architecture diagram above.
Following the control flow, we have an HTTP Request that reaches the Controller. The controller will then:
- Dismantle the Request;
- Create a Request Model with the relevant data;
- Execute a method in the Interactor (which was injected into the Controller using the Interactor’s interface, the Boundary), passing it the Request Model;
- The Interactor:
- Uses the Entity Gateway Implementation (which was injected into the Interactor using the Entity Gateway Interface) to find the relevant Entities;
- Orchestrates interactions between Entities;
- Creates a Response Model with the data result of the Operation;
- Populates the Presenter giving it the Response Model;
- Returns the Presenter to the Controller;
- Uses the Presenter to generate a ViewModel;
- Binds the ViewModel to the View;
- Returns the View to the client.
The only thing here where I feel some friction and do differently in my projects is the usage of the “Presenter“. I rather have the Interactor return the data in some kind of DTO, as opposed to injecting an object that gets populated with data.
What I usually do is the actual MVP implementation, where the Controller has the responsibility of receiving and responding to the client.
I would not say that the Clean Architecture is revolutionary because it does not actually bring a new groundbreaking concept or pattern to the table.
However, I would say that it is a work of the utmost importance:
- It recovers somewhat forgotten concepts, rules, and patterns;
- It clarifies useful and important concepts, rules and patterns;
- It tells us how all these concepts, rules and patterns fit together to provide us with a standardised way to build complex applications with maintainability in mind.
When I think about Uncle Bob work with the Clean Architecture, It makes me think of Isaac Newton. Gravity had always been there, everybody knew that if we release an apple one meter above the ground, it will move towards the ground. The “only” thing Newton did was to publish a paper making that fact explicit*. It was a “simple” thing to do, but it allowed people to reason about it and use that concrete idea as a foundation to other ideas.
In other words, I see Robert C. Martin is the Isaac Newton of software development! 🙂
2012 – Robert C. Martin – Clean Architecture (NDC 2012)
2012 – Robert C. Martin – The Clean Architecture
2012 – Benjamin Eberlei – OOP Business Applications: Entity, Boundary, Interactor
2017 – Lieven Doclo – A couple of thoughts on Clean Architecture
2017 – Grzegorz Ziemoński – Clean Architecture Is Screaming