So what is Domain Driven Design (DDD)? The exact explanation may require very lengthy explanation so that is why Eric Evans have to wrote a book about it. But in short, DDD allows us to take out complexities when developing software by using OOP techniques.
What OOP techniques that we’re talking about? DDD heavily influenced by Martin Fowler’s Analysis Patterns book. I’ve read Fowler’s book for years and I can’t understand how to implement them. But once I understand DDD, everything fall in place easily.
Beside Analysis Patterns, DDD also advise us to use Design Patterns heavily. Design Patterns from GoF is discussed and included as part of DDD but it also borrows techniques from contemporary pattern with its own twist. For instance, the Repository pattern on DDD is slightly different then regular Repository pattern in early 2000s.
Let’s go directly to the example.
Let say we want to create a loyalty points system. Since writing software is a team work, DDD allows us to use Ubiquitous language. One single language that we use to communicate between team members. Especially between the developer and the customer or the product owner or the domain expert, let’s call them the domain expert from now on.
So the first step of DDD is to have a workshop with the domain expert to design a model or a class diagram which will be used to understand the domain and then implement them in the chosen programming language.
When discussing the domain expert we found out that the system has users and each user is identified using their phone number. Now, in DDD this kind of class is called Entity. An Entity must have a unique id. And this Entity concept is just like what it found in database concept. Which is the first normal form. So let’s draw User in our domain models:
Why there is User class and PhoneNumber class? And what is Value Object?
So, the User class is an Entity. Since it is an Entity it requires a unique identifier which is a Phone with has type PhoneNumber.
The PhoneNumber class is a Value Object which means it doesn’t requires any unique identifier. The Value Object must be immutable. The PhoneNumber class separated into its own class that means we can reuse this class. And the class already include a validation to validate the passed value is a valid PhoneNumber. And in DDD when you instantiated an object you have to validate the properties of the object is valid or in mathematical words, the invariant of the object if fulfilled.
The domain expert also says that the User can be identified by a merchant Id. The user has points. And that points can be added also can be deducted. The system must maintains the total points of the user. The points also has expiration date. This is the next iteration of the model:
This is one very powerful concept that I believe unique to DDD. But the term is very vague. What is Aggregate? It is not a word that used commonly in daily life. But once you understand it you will realise how powerful it is and how it simplifies RDBMS locking mechanism. Hence, simplifies system scalability. Fowler describe Aggregate clearly in his website:
Aggregate is a pattern in Domain-Driven Design. A DDD aggregate is a cluster of domain objects that can be treated as a single unit. An example may be an order and its line-items, these will be separate objects, but it’s useful to treat the order (together with its line items) as a single aggregate.
An aggregate will have one of its component objects be the aggregate root. Any references from outside the aggregate should only go to the aggregate root. The root can thus ensure the integrity of the aggregate as a whole.
Aggregates are the basic element of transfer of data storage — you request to load or save whole aggregates. Transactions should not cross aggregate boundaries.
Every Aggregate must have an Aggregate Root. An Aggregate Root must be an Entity. Remember that!!!
From our model we can choose to have two aggregates: Merchant aggregate and User aggregate. Here is the updated model:
Each aggregate must have its own repository. So what is a repository? A repository is an abstraction of the persistence mechanism that will be used in the system. If the persistence mechanism chosen is a RDBMS then one repository must only have one transaction and no cross transaction between repositories. With this aggregate concept the whole system performance will be easier to understand and it can forbid deadlocks. Since every time we do updates in RDBMS we must lock the aggregate root. Bear in mind the Repository pattern in DDD is slightly different with common Repository pattern which is one class one Repository.
How to Implement The Model In Code?
One thing that I really love about DDD is the rule that every time you create an object the object should throw error if the values passed to it is not valid. So that means once an object created then it is already valid and you don’t have to worried about handling more error in your code. Since once you have a PhoneNumber instance then it is guarantee it is a valid PhoneNumber.
Also DDD must not have regular setter just like traditional OOP programming. But every operation or behavior must invalidate the variant of the object. As you can see when we put PhoneNumber in its own class we can put many methods or behaviors on the class related to PhoneNumber. This means reusability will be increased. Hence faster delivery time.
From the implementation of the repository you can see that every time we want to load the User object from the persistence mechanism then we must also load his PointEntries. And every time we want to save the User, we must also save his PointEntries.