Reference: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
- Formal Definition.
- Generalization of Clean Architectures
- Only Four Circles?
- Typical Example
The Clean Architecture style aims for a loosely coupled implementation focused on use cases and it is summarized as:
-
It is an architecture style where the Use Cases are the centran organizing structure.
-
Follows the Ports and Adapters pattern.
- Implementation guided by tests (TDD Outside-In).
- Decoupled from technology details.
- Follows lots of principles (Dependency Rule, Stable Abstractions Principle, Stable Dependencies Principle, SOLID, and so on).
By separating the software into layers, and conforming to The Dependency Rule, you will achieve separation of concerns and create a system that is intrinsically testable, with all the benefits that implies. When any of the external parts of the system become obsolte, you can replace those with a minimum of fuss.
- Hexagonal Architecture (Ports and Adapters) by Alistair Cockburn and adopted by Steve Freeman, and Nat Pryce in their book Growing Object Oriented Software.
- Onion Architecture by Jeffrey Palermo.
- Screaming Architecture from Robert C Martin.
- DCI from James Coplien, and Trygve Reenskaug.
- BCE by Ivar Jacobson from his book Object Oriented Software Engineering: A Use-Case Driven Approach.
Though architectures all vary somewhat in their details, they are very similar. They all have the same objective, which is the separation of concerns. They all achieve this separation by dividing the software into layers. Each has at least one layer for business rules, and another for interfaces.
Each of these architectures produce systems that are:
-
Independent of Frameworks. The architecture does not depend on the existence of some library of feature laden software. This allows you to use such frameworks as tools, rather than having to cram your system into their limited constraints.
-
Testable. The business rules can be tested without the UI, Database, Web Server, or any other external element.
-
Independent of UI. The UI can change easily, without changing the rest of the system. A Web UI could be replaced with a console UI, for example, without changing the business rules.
-
Independent of Database. You can swap out Oracle or SQL Server, for Mongo, BigTable, CouchDB, or something else. Your business rules are not bound to the database.
-
Independent of any external agency. In fact your business rules simply don’t know anything at all about the outside world.
No, the circles are schematic. You may fin that you need more than just these four. However, The Dependency Rule always applies. Source code dependencies always point inwards.
This diagram shows a typical scenario for a web-based Java system using a database.
-
The web server gathers input data from the user and hands it to the
Controller
on the upper left. TheController
packages that data intoInputData
interface as a plain old Java object and passes this object trough theInputBoundary
to theUseCaseInteractor
. -
The
UseCaseInteractor
interprets that data and uses it to orchestate theEntities
. It also uses theDataAccessInterface
to bring the data used by thoseEntities
into memory from theDatabase
. -
Upon completion, the
UseCaseInteractor
gathers data from theEntities
and constructs theOutputData
as another plain old Java object TheOutputData
is then passed through theOutputBoundary
interface to thePresenter
. -
The job of the
Presenter
is to repackage theOutputData
into viewable form as theViewModel
, which is yet another plain old Java object. TheViewModel
contains mostlyStrings
and flags that theView
uses to display the data. Whereas theOutputData
may containDate
objects, thePresenter
will load theViewModel
with correspondingStrings
already formatted properly for the user. The same is true for any other business-related data. -
This leaves the
View
with almost nothing to do other than to move the data from theViewModel
into the HTML page.
Note the directions of the dependencies. All dependencies cross the boundary lines pointing inward, following the Dependency Rule.