In order to easily identify, understand and manipulate the code that reflects the domain, we need to isolate it from all the support code, the code that allows for user interaction (views, controllers) and the code that allows for data persistence and retrieval.
The most widely used and easy to understand approach is to isolate the code into layers:
- User interface: Views to interact with the user;
- Application: Controllers to specify use cases;
- Domain: Business rules that reflect the model;
- Infrastructure: Persistence, queues, … ;
The previous layers are the most common and generic, but there can be other configurations. Nevertheless, central to DDD is the isolation of the domain layer.
This layer segregation provides:
- Easier maintainability;
- Easier development;
- Easier deployment segregation, allowing i.e. different layers to be in different servers;
When segregating layers, each layer should be dependent only on the layer below. However, in highly complex systems we will end up having the need to fire logic in the top layers when something happens in a lower layer. For example, when an object is persisted with a specific change, we need to fire the logic to send out an email. This type of behaviour can be solved by using callbacks, Observers or Events.These types of solutions should be provided by the framework, however developers should use these handy framework solutions rationally, so not to run the risk of ending up with a bloated and slow application, who is also tightly coupled to the framework.
As Robert C. Martin (Uncle Bob) refers in one of his talks, “the framework is an implementation detail”, meaning that the framework is NOT the reason our application is better than others, nor why it is innovative, nor why it delivers more functionality to users. The Business Logic, the Domain is! The domain implementation IS in fact our application.
Personally, I feel we should be able to, at any given moment and for any reason, with relatively low difficulty and no changes to the domain implementation, be able to switch to other, more performant, framework. Also, the same way we currently are able to switch ORM and keep the same FW, we should be able to switch FW and keep the same ORM.