Cumulus, Sherweb’s one-stop shop platform for provisioning cloud services, was designed with Domain-Driven Design (DDD) in mind in early 2012. Throughout the years, we’ve been able to identify both the benefits and the pitfalls of using DDD. The goal of this new blog series is to share our field experience and help you determine if Domain-Driven Design is ideal for your current or next project.
We’ve made sure to list references and books at the end of this blog article, so those of our readers who don’t know much about Domain-Driven Design can quickly catch up! Now, let’s start with the key benefits.
3 Key benefits of using Domain-Driven Design
Speaking the same language
Have you ever experienced this issue: Speaking with a non-technical person (Domain Expert, Stakeholder, Product manager, etc.) and noticing that you’re not using the same words when talking about business concepts modeled by the software? Domain-Driven Design addresses that with the concept of “Ubiquitous Language”.
But what is an “Ubiquitous Language » and why is it so beneficial?
What is most important as a developer is to be able to use terms in your code that a non-technical person can understand. What your code is trying to achieve should only be a reflection of what your company processes are, therefore it makes sense to use the same vocabulary your company uses with clients, during meeting conversations, in user interfaces, etc. That’s where the Ubiquitous Language comes in, forcing developers to use proper naming for Aggregates, Entities and Value Objects in order to represent what a Domain Expert is using daily. For a developer at Sherweb, it means talking with our analysts, our product managers or architects to find out the proper wording for a given Bounded Context. The Ubiquitous Language will not only help you clarify your backend class names, but it will also help you choose the words your end clients are more likely to understand for the user interface. By using the same term for a class, developers won’t need to translate their code to a Domain Expert, hence reducing the chances of being misunderstood!
The following image shows how the Ubiquitous Language is common ground for both the Domain Experts and the Developers.
The new revamped Advisor portal that we launched recently at Sherweb is a good example. The backend structure of the Advisor Portal is built with a better comprehension of what Domain-Driven Design is and it uses our Ubiquitous Language. You can see here how we’ve been able to name our Aggregates properly in the code:
Those are the words that our Product Manager use and we’ve used the same in our new Advisor Portal. But what if we decided we didn’t like those and rather used:
There’s no way our Product Manager would understand any of these terms if we went to him and didn’t translate them in “his” language.
Encapsulating the business logic in Aggregates
An important part of an enterprise application revolves around the business logic it holds. Domain-Driven Design brings in the concept of Aggregate to help us achieve a better encapsulation of the business logic.
What is an invariant?
Invariants are business rules that must be protected throughout the entire lifetime of an Aggregate from the moment it is constructed until it is persisted to disk.
Let’s take for example a Sherweb Partner, invariants could be:
- Name must have a length of 3 to 15 characters
- All of the primary contact fields must be
- The creation date must not be in the future
- A partner must have at least 1 contact.
But what if we have a method “ChangePartnerName(string name)” in the class Partner? The invariant still needs to follow the same constraints and go through the same validations.
The same thing happens for a method that removes a contact. We have to respect the invariants. If you try to remove the last contact of a Partner, then it must throw an exception because a Partner must have at least one contact.
Scalability through Bounded Contexts
Sherweb went from a team of 4-6 people working on Cumulus to the whole department. It became messy at some point, as each team had to know the whole system and each meaning behind each word of the Ubiquitous Language of each Domain. We realized that it was no longer possible to run the department properly and that it would not sustain the practice in the long run. We then adapted our processes with Domain-Driven Design by assigning a team per Domain. For us, it meant assigning one team to the “Billing domain”, one to the “Provisioning domain” and another one to the “Offering domain”. It worked well, but we wanted more flexibility! So we decided to change once again our processes and split each Domain in multiple Bounded Contexts. With this approach, we were able to assign one team per Bounded Context. For example, the Billing Domain was separated into 2 Bounded Contexts: Invoicing and Payment.
As of today, we can quickly scale to work on different projects at the same time by assigning each team to a specific Bounded Context for the next sprint iteration. We’re able to do this because each Bounded Context is self-contained and detached from other Bounded Contexts, which means Team A can work on Bounded Context A without worrying about affecting the Bounded Context B that Team B is working on during the same sprint iteration.
A good example of that method would be the following image from Microsoft MSDN. A team can effectively work on Bounded Context A (Conference Reservations) while another team works on Bounded Context B (Program Management) because those bounded contexts have their own Ubiquitous Language, Entities, Aggregates and so on.
References and books