Clean Architecture
Last updated
Last updated
It is a model with the objective of decoupling the application independent business rules (or domain), from external resources (like frameworks, DBs).
Independent Business Rules
, are business rules that are independent of context (should be followed despite of where are executed).
Ex.: Business Rules that aren't valid only in specific Usecases.
Clean Architecture is Usecase
driven.
In a way every Clean Architecture
is also Hexagonal Architecture (Ports and Adapters), but the opposite is not.
In Hexagonal Architecture
you don't have the distinction of usecases and entities, you only have the application (hexagon) which is the sum of usecases with entities.
The project folder names is completely irrelevant to the Layers
.
You can have Layers
without folders separating the files.
They are responsible for abstracting the Independent Business Rules
, which can be from an object with methods to a group of functions.
Ex.:
Is CarPlate
valid?
What is the distance between two Coords
?
How much is the Ride Fare
?
How the Ride Status
change?
Entities can be broken in Aggregate, Entity, Value Object and Domain Service by using DDD (Domain Driven Design).
Clean Architecture
don't clearly specify what an Entity
can be as DDD
does.
DDD
strongly complements Clean Architecture
Entity Layer
.
Anemic means that an Object only handles Properties (State)
OR Behavior
, but not both.
They orchestrate the entities and external resources, meaning they will be sort of a bridge between Entities
and Interface Adapters
.
Usecases are behaviors offered to the Clients. (You application exists because of your exposed Usecases)
Usecase names are related to [[Screaming Architecture]], which states to give names related to what it does.
Very rarely a Usecase A
will call another Usecase B
.
But this still increases coupling in the Usecase A
, increases time to complete the Usecase A
.
In very simple cases, a Usecase can be the same as CRUD operations.
But as complexity increases they will be less alike.
These are the bridges between Usecases
(High level) and External Resources
(Low level).
This is where you:
Treatment of requests and HTTP responses. (Dealing with parameters)
Access the Database. (All the SQL
code belongs here)
Integrate with External APIs.
Read and Write to files. (Interact with Filesystem)
Convert data. (Like convert to CSV
, PDF
)
Here lies the lowest level of abstraction.
Where you actually interact with technology, with the components that connect to the Database
, that deal with the HTTP requests
, that interact with the filesystem
or access S.O resources
.
The ideia in here is to abstract only some level of the technology used, so that the Interface Adaptors
won't know for instance if they will connect to a Postgres or MySQL database.
But there is a certain level of restriction for decoupling External Interfaces.
Ex.: You may not be able to write a contract for the Database connection that works on unsimilar technologies. (Like Postgres
and Mongo
)
Interface Adapter
vs External Interfaces
In Hexagonal Architecture (Ports and Adapters), there is no difference between Interface Adapters
and External Interfaces
, they are the same.
An example of mixing Interface Adapters with External Interfaces would be:
Having the code that connects to the Database inside a Repository like this.
So, there is a certain level of coupling of Postgres
with our Interface Adapter
that is called from the Usecase
.
The inner layers (high level) should not know implementations of external layers (low level), which is .
Entity
ORM object entity
. (Which is a mere database table representation)
So, instead of calling Usecases inside another Usecase, use Design Pattern to decouple these Usecases by using a bus/channel
like a queue
, for communication between them. (Not necessarilly an external tool like RabbitMQ
)