Domain Driven Design
Domain driven design comes in domain layer in the layered architecture. There we are not concerning about any particular technology or infrastructure, but object oriented concepts. We capture domain elements and represent them in object oriented concepts like objects, methods, etc. The design needs to be both nice and usable. The design which is nice but not usable is not worth and vice versa. When designing, we need to think whether we can implement this design in the real world. We should not keep two separate designs for analysis & design phase and for implementation. It should be the same design we should implement. Although there is a feedback loop through out the life cycle, the same design should continue through out the all stages of the software life cycle.
We should avoid mismatch between domain experts and software developers.
We should also avoid;
- Usage of multiple words to represent the same thing. For example debit & credit and withdraw & deposit to represent the same thing.
- Usage of one word to represent two things.
If we take university domain there we can identify several services which are related to that domain. For example canteen, library, bookshop, examination dept, etc. Canteen, bookshop can be given as examples for infrastructure service and examination, other departments are examples for domain services. We can use services to capture responsibilities and system requirements which are not directly related to the domain. Without services we assign that responsibility to some other class which is not good. Because a class should have only one responsibility assigned to that. We use artificial classes to assign those responsibilities as services.
To avoid complexity, we use modules. Divide and conquer is the method used to handle complexity. Since one person can’t comprehend the whole complexity, can use modules. We should remove dependencies between modules, so that they can be handled independently. Within sub system or modules, there exists high level of coupling. But between modules coupling is less. These modules also should reflect domain concepts like module naming, etc.
Aggregates and aggregate roots:
Also known as concurrency control and ownership. Every aggregate has a boundary. If we take a look at the figure above, can’t change contact info or address without knowing the customer. Customer is the owner of it. If two people are going to change this information, there would be concurrency issues. Customer is the one who have the control over the contact info and address.
Object life cycle:
Objects have a life cycle staring with creation, then retrieving, and ending with deletion. Use factories to create complex objects. Otherwise use a constructor. Consider previous figure; if all customers need to have contact information and how we are t enforce this rule? It’s not a customer class responsibility. So create a factory and assign that responsibility.
By: W.A.A.D. Wickramaarachchie