Domain-driven design is focused at the Domain Layer which is one of the common layers in an object-oriented system with a multi layered architecture. Complex domain designs should be based on a model. The domain model should form a common language for describing system requirements, that works equally well for the business users or sponsors and for the software developers. In Domain-driven design, we only need to concern about 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 as it is the foundation for rest of other stages of software life cycle. When designing, we need to think whether we can implement this design in the real world. We should be able to change the technology, if we couldn’t achieve the design with the existing technology. We should not keep two separate designs for analysis & design phase and for implementation. Design model and the implementation model should be aligned. There should be feed back loop through out the life cycle.
It is needed to avoid mismatches between domain experts and software developers. Multiple words can be used to represent same things and one word can be used to represent the two things. We should avoid those kinds of language ambiguities.
Model Driven Design is broken down into the following artifacts:
- Value Objects
Each one of these artifacts complements one another and allows us to gain greater insight into the business domain. Ubiquitous Language is the backbone or glue rather that holds all these artifacts together.
Services: Services are not part of the domain, but need to carry out the domain. Considering bank domain, transactions can be identified as domain services and providing pawning, and secure safe are some examples for infrastructure service. We can use services to capture responsibilities and system requirements which are not directly related to the domain. Class should have only one responsibility assigned to it.
Modules: In a complex system the model tends to grow bigger and bigger, so it is necessary to organize the model into modules. Therefore modules are used to avoid complexity. Divide and conquer is the method used to handle complexity. Dependencies between modules should be removed. Modules should be able to handle independently. Coupling should be less between modules. These modules also should reflect domain concepts like module naming.
Aggregate: An Aggregate is a group of associated objects which are considered as one unit with regard to data changes. Every aggregate has a boundary. It can be divided into normal aggregates and root aggregates. Root aggregate is the owner of other classes within the boundary. The root holds references to any of the aggregate objects, and the other objects can hold references to each other, but an outside object can hold references only to the root object.
Factories: Objects have a life cycle staring with creation, then retrieving, and ending with deletion. Factories can be used to create complex objects as hierarchies. When a Factory is not needed, we can use simple constructor to create objects. We have to identify correctly when factory is needed. Factories need to create new objects from scratch, or they are required to reconstitute objects which previously existed,