Lets start with implementation and work back to analysis:
Earlier article on the topic: http://know.iteonline.co.za/?p=78
This kind of architecture implementation is not designed in layers any more, but is more like an Onion. The core is surrounded by I/O to other aspects which have been de-centered on purpose.
At the core of the bulb – sorry, of the system, you have the Domain Model.
It implements all Value Objects and Entity Objects, including their state and behavior, and associated unit tests.
Around this core, you find Domain Services which add some more behavior to the inner model.
Typically, you will find here abstract interfaces that provides persistence (Aggregates saving and retrieving via the Repository pattern), let Domain objects properties and methods be defined (via the Factory pattern), or access to third-party services (for service composition in a SOA world, or e.g. to send a notification email).
Then Application Services will define the workflows of all end-user applications.
Even if the core Domain is to be as stable as possible, this outer layer is what will change more often, depending on the applications consuming the Domain Services. Typically, workflows will consist in deshydrating some Aggregates via the Repository interface, then call the Domain logic (via its objects methods, or for primary operations with wider Domain services), call any external service, and validate (“commit”, following Unit-Of-Work or transactional terms) objects modifications.
Out on the edges you see User Interface, Infrastructure (including e.g. database persistence), and Tests. This outer layer is separated from the other three internal layers, which are sometimes called Application Core.
This is where all technical particularities will be concentrated, e.g. where RDBMS / SQL / ORM mapping will be defined, or platform-specific code will reside. This is the right level to test your end-user workflows, e.g. using Behavior-Driven Development (abbreviated BDD), with the help of your Domain experts.
The premise of this Architecture is that it controls coupling. The main rule is that all coupling is toward the center: all code can depend on layers more central, but code cannot depend on layers further out from the core. This is clearly stated in the above diagram: just follow the arrows, and you will find out the coupling order. This architecture is unashamedly biased toward object-oriented programming, and it puts objects before all others.
This Clean Architecture relies heavily on the Dependency Inversion principle. It emphasizes the use of
interfaces for behavior contracts, and it forces the externalization of infrastructure to dedicated implementation classes. TheApplication Core needs implementation of core interfaces, and if those implementing classes reside at the edges of the application, we need some mechanism for injecting that code at runtime so the application can do something useful. mORMot‘s Client-Server features provide all needed process to access, even remotely, e.g. to persistence or any third party services, in an abstract way.
With Clean Architecture, the database is not the center of your logic, nor the bottom of your physical design – it is external. Externalizing the database can be quite a challenge for some people used to thinking about applications as “database applications”. With Clean Architecture, there are no database applications. There are applications that might use a database as a storage service but only though some external infrastructure code that implements an interface which makes sense to the application core. The domain could be even decoupled from any ORM pattern, if needed. Decoupling the application from the database, file system, third party services and all technical details lowers the cost of maintenance for the life of the application, and allows proper testing of the code, since all Domain interfaces can be mocked on purpose.
This is the Analysis toolset and approach: