Like my other post about Clean Architecture, I will now write about Domain-Driven Design.
What is Domain-Driven Design?
Domain-Driven Design, as it states in the title is putting the domain in the center of developing software. Domain Driven Design was first written about by Eric Evans in his book Domain-Driven Design: Tackling Complexity in the Heart of Software. This was a completely new way of thinking about Software Development.
The first D i DDD: Domain
A domain is a field of study, where you identify and define common cohesions which in total gives a set of descriptive requirements, terminologies and functionalities that is specific for one domain or one or more subdomains problems. This set is not static and can be dynamically changed if changes to the domain happen.
Eric Evans reference book has the following definition:
A sphere of knowledge, influence, or activity. The subject area to which the user applies a program is the domain of the software.
Taking the Domain to the Software
On my education we have been taught about Model-View-Controller (MVC), Model View-Model View (MVVM) and so forth as architectural patterns. These architechures, or way of designing software systems, are with the model in the center. The model is a system of abstractions that together can solve the problems related to the domain. Here we have been taught in Craig Larmans book about Applying UML and patterns. This Model Driven Architecture or Model Driven Design often use UML as a way of describing the problem domain. However, it can often end up being data-centric and therefore the opposite of DDD. In data-centric architectures you maybe start caring too much about how your data structures are, how the database is setup and so forth. If you can stop focusing on this, and focus on the model as a domain model, there is actually alot of similarities to DDD.
As DDD does not explicit say you need to use UML, it could be a good way of designing you DDD application. It is just important to make sure the domain model stays as the domain.
I would definitely use UML in my further investigation and implementation of DDD in our services.
But how do we understand the domain?
DDD’s Ubiquitous Language
The DDD strongly suggest to use Ubiquitous Language. Is a term for the practice where you build a common language with the domain experts and users, so when you talk about the domain there shouldn’t be any ambiguities. This is often done by making a glossary of words and their meanings, so everyone is on the same page. This glossary should be a a cornerstone for you naming classes and so forth in your desired language. This makes the job of structuring your solution a lot easier.
The Ubiquitous Language can be different in different contexts. Therefore you usually define bounded contexts for each subdomain. An example of this could be that an Order department does not have the same definition of an Order as a Stock department - they are different because of the context.
In Microservices you often define your services in the different context - so in the example above the Order department will be an service in it self, with it’s own definition of a Order and Stock department will have its own service, with it’s own definitions.
How to structure in Domain Driven Design and Onion Architecture
In DDD you have definitions for different objects.
- has their own identifier, meaning they need an identifier field such as and Id property or something similar. They have their own inherent identity.
- should have a history - what changes happened to them.
- is mutable - open for change.
An Value Object
- does not have their own identifier. We only look at the structural identity - if it’s the same properties for both value object, they are the same.
- should not have a history - we create them in memory, and destroy them afterwards. If we need a copy, we just make a new instance.
- can not live alone. They should be a part of an entity.
- is immutable - if you can’t make it immutable is not a value object.
- is an cluster of domain objects that can be treated as a single unit - Martin Fowler. Fx. an Customer maybe an Entity, this Entity relies on an Order also and Entity, but this Entity relies on an LineItem or OrderLineItem. Therefore a Customer is the aggregate root in this example. A way of testing this is, if we delete the Customer, should all the corresponding entities also be deleted, resulting in a cascade deletion? The answer is, YES.
An Domain event
- an object encapsulation an event that is spefic to the domain. This could fx. be a CustomerHasBeenCreated. These events can be used to communicate with other services.
These are the typical domain objects you will see.
How are they placed in the Onion Architecture?
Domain objects are often placed in the Core of the Application. Domain event handlers will be placed in the Domain as a Domain Service. Here you can implement more business logic. Many experts say that your abstractions should be placed in the Core - the abstractions are often referred to as the most volatile components. This means that if you where to implement a repository the interface, like IRepository, would be placed in the core, and the persistence/infrastructure would have a concrete implementation of that.
A typically C#/.NET Core structure would be as follows.
Next up will be my implementation of a service with follows the DDD principles.