Domain-driven design (DDD) is a software development philosophy centered around the domain, or sphere of knowledge, of those that use it. The approach enables the development of software that is focused on the complex requirements of those that need it and doesn’t waste effort on anything unneeded. The clients of domain-driven design are often enterprise-level businesses.
To design from a domain-driven perspective, the business's area of expertise or domain must be defined. There are supporting and core domains. The core domain of a business is unique and central to its operation, therefore receiving the majority of attention, time and resources in the development process. The supporting domains are more general such as money, service or time. These domains are then modelled out in language and then in corresponding code. If a domain can’t be easily defined in language, it is not ready to be coded. If a change is made in a domain of business, a corresponding change in the code would generally be required.
DDD Layered Architecture
Presentation Layer or UI (User Interface) Layer : the easiest to understand, this layer is the responsible of displaying information to the user, and accept new data. It could be implemented for web, desktop, or any presentation technology, present or future. For example, it could be a voice application, that interacts with the user via a phone. The acid test for our design is that a radical change in user interface should have minimal (or controlled, at least) impact in the rest of the system.
Application Layer: it’s in charge of coordinating the actions to be performed on the domain. There are no business rules or domain knowledge here. No business state resides in this layer. It delegates all domain actions to the domain. It could coordinate many actions (possibly in many domains). It could prepare the infrastructure to be ready to work with the domain for an specific action (for example, preparing transaction scopes).
Domain Layer: In this layer resides the heart of software, according to Evans. Business rules and logic lives inside this layer. Business entity state and behavior is defined and used here. Communication with other systems, persistence details, are forwarded to the infrastructure layer. Evans discuss the patterns he uses in this layer, as Entities, Value Objects, Services, Repositories and Factories. We would explore the patterns and implementations in future posts.
Infrastructure Layer: God and devil are in the details, and in the infrastructure layer. Its main responsibility is the persistence of the business state, most frequently, using a relational database.
Domain-Driven design approach
The majority of frameworks under Spring data family is built considering Domain-Driven design approach.
1. The strategic pattern will help you design your domains, sub-domains that are communicated by the ubiquitous language then support you to organize/structure your teams based on that outcome.
2. The tactical pattern will guide you on how to implement your application in a scaling way.
1. Strategic Design :
The strategic design tools help us to solve all problems that are related to software modeling. It is a design approach that is similar to Object-oriented design where we are forced to think in terms of objects. Herewith strategic design we are forced to think in terms of a context.
Context : We can consider this an English word that refers to circumstances of an event, incident, statement, or idea, and in terms of which it’s meaning could be determined.
Apart from Context, Strategic design also talks about Model, Ubiquitous Language, and Bounded Context. These are common terms used in strategic Design of Domain-Driven Design. Let’s understand each one by one.
Model – It acts as a core logic and describes selected aspects of domain. it is used to solve problems related to that business.
Ubiquitous Language – A common language used by all team members to connect all activities of team around domain model. Consider it like using common verbs and nouns for classes, methods, services, and objects while talking with domain experts and team members.
Bounded Context – It refers to boundary conditions of context. It is a description of a boundary and acts as a threshold within which, a particular domain model is defined and applicable.
2. Tactical Design :
Tactical design talks about implementation details i.e., modeling domain. It generally takes care of components inside a bounded context. We might have heard or used stuff like services, entities, repositories, and factories. They have all coined and made popular by Domain-Driven design. The tactical design process occurs during product development phase.
Below are some of important tactical design tools. These tools are high-level concepts that can be used to create and modify domain models.
Entity – A programmer who has worked on Object-oriented principles might be aware of concepts called class and objects. Here an entity is a class that has some properties. The instance of these classes has a global identity and keeps same identity throughout lifespan. Remember there can be a change in state of property but identity never changes. In short, an entity implements some business logic and could be uniquely identified using an ID. In context of programming, it generally persisted as a row in DB and it consists of value objects.
Value Objects – These are immutable, light-weight objects that don’t have any identity. Value objects reduce complexity by performing complex calculations, isolating heavy computational logic from entities. In the above image User is an entity and Address is a value object, address can change many times but identity of User never changes. Whenever an Address gets change then a new Address will be instantiated and assigned to User.
Services – A service is a stateless class that fits somewhere else other than an entity or value object. In short, a service is a functionality that exists somewhere between entities and values objects but it is neither related to an entity nor values objects.
Aggregates – When we have bigger project, object graph becomes big, The bigger object graph harder it is to maintain it. An aggregate is a collection of entities and values which come under a single transaction boundary. Aggregates basically, control change and have a root entity called aggregate roots. The root entity governs lifetime of other entities in aggregates. In the above example if root entity User or Order gets deleted other entities associated with the root entity will be of no use and this associated information will also be deleted. That means an aggregate is always consistent in nature and this done with help of domain events. Domain events are generated to ensure eventual consistency. In the above example if address of User has been changed then it has to be reflected in Order as well. To do so we can fire a domain event from User to Order so that Order updates address so that we have eventual consistency and Order will be eventually consistent. Other examples of aggregates and aggregate root could be comments on a post, Question and answer details, Banking transaction details, etc. The ORM tool like hibernate uses aggregates a lot while creating one to many or many to one relationship.
Factories and Repositories – Factories and Repositories are used to handle aggregate. Factories help in managing beginning of lifecycle of aggregates whereas Repositories help in managing middle and end of lifecycle of an aggregate. Factories help in creating aggregates whereas Repositories help in persisting aggregates. We should always create a repository per aggregate root but not for all entities.
Advantages of Domain-Driven Design :
It improves our craft.
It provides flexibility
It prefers domains over interface
It reduces communication gap between teams through Ubiquitous Language
Disadvantages of Domain-Driven Design :
It requires a professional who has strong domain expertise
It encourages team to follow iterative practices
The Tech Platform