This post was initially published on DZone. Nonetheless, I made few changes here based on what i’ve been implementing for Pearl Data Direct
The first time I heard about DDD (Domain Driven Design, not Deadline Driven Design, for sure), I was still working as a Senior Java Developer for Hewlett-Packard at its Development Center in Cyberjaya – Malaysia. I wasn’t quite interested in the topic since it was difficult to get a good resource during that particular time. Someone told me to find Eric Evan’s book (“the blue book”), thus i bought and added it to my PDF collection.
During that time, DDD was quite new and not many knows about it, particularly on how to correctly implement it in a project. Thus only a few companies had successfully implemented this new thing. And somehow, I found that many DDD resources were too difficult to be grasped by most of the readers (i.e. they are too abstract and lack of good examples). Therefore, i’m planning to pick up this awesome topic and write it in a series, equipped with an application sample to be followed step by step.
This is the first part of other series those are still in my head as follow:
- DDD Part 1 Introduction → You are here
- DDD Part 2, Context Map
- DDD Part 3, DDD Building Blocks
- DDD Part 4, DDD and Hexagonal Architecture
- DDD Part 5, DDD and Microservices
- DDD Part 6, Code Implementation
- DDD Part 7, ES and CQRS — DDD’s best part (coming soon)
In this first part of Introduction, I would like to start with some basic concepts as written below:
- What is DDD all about?
- How do we get started?
- What should we avoid in DDD?
Let’s get started!
1. What Is DDD All About?
To start this section, I’d rather take the definition from one of DDD’s communities, dddcommunity.org, that describes DDD as an approach to developing software for complex needs by deeply connecting the implementation to an evolving model of the core business concepts.
As the definition implies, DDD is suitable for you if you’re building software that has complexity in its business process (business domain). So, not every software is suitable for DDD (e.g. CRUD applications aren’t suitable for it since they’re not so complex).
Teamwork is very important within DDD since you need to keep in touch with the users/clients (a.k.a Domain Experts). Moreover, you build the software for them, not for you (you got the point right). Just like someone said: “the software can fail either in two ways, you build the things wrong or you build the wrong things.” In that case, you have to ensure that you understand the business that you’re going to build. This is what DDD is all about.
To summarize, DDD can be described as a technique for developing software that focuses on collaboration between technical experts and domain experts. Therefore, we must keep focus with the domain experts instead of the nitty-gritty details of the technical stuff.
2. How Do We Get Started?
First things first, as mentioned earlier, the big point is to keep in touch with the business/domain expert. I will recap several points those we can use as guidance while we have a discussion with the domain expert:
- Learning about the problem domain, i.e. the specific problem the software you’re working on is trying to solve. Domain should be the one that you focus on (heart of the system, which is one and only one). Domain should be reflected by the software/system you built. Look at the big picture of the current business process. Trying to modeling your domain as a white-box.
- Each domain can be structured in sub-domains and there can be communication between various sub-domains. Hence, the next step is to breaking the domain into sub-domains. For instance, let’s say our core domain is Treasury. Inside treasury, there should be more than one sub-domains. With that said, we could imagine our Treasury in a white-box model as depicted below:
- Focusing on one sub-domain at a time with the domain expert, and always use ubiquitous language to define working out terminology.
- Creating a bounded context between sub-domain, and discuss how domains, sub-domains, and especially bounded-contexts relate to each other. This is known as “Strategic Design” which could be considered as the first phase when we’re working with DDD. Furthermore, “Strategic Design” will help us in figure out the context mapping and the context map’s patterns such as shared-kernel, customer-supplier, anticorruption-layer, or published-language among others, to analyze existing applications or application landscapes for possible transformations of a monolithic application. At the end, we will understand how the idea of a bounded-context can relate to microservices.
- Ubiquitous language should always be used throughout the bounded context, from conversations to code, in the diagram, on the whiteboard, in the design document, team discussion, etc. The point is to use the bounded context everywhere.
- Ideally, there will be a different team, codebase, and database for each bounded context.
- Since everyone is working for their bounded context, so they are free to change anything within their context.
- For all cross-cutting concerns those are shared between bounded context (we call it shared kernel), any changes should be known and agreed between all team in every bounded context.
- Always stay focused on the domain’s behaviors rather than domain’s state (favor a rich model over an anemic model).
To summarize, always use ubiquitous language (i.e. same terminology) across the team, break the domain into smaller subdomains and give an isolation (i.e. bounded context) by defining the boundary and think about how the subdomain within the bounded context can communicate to each other using interfaces/crafted software contract.
3. What Should We Avoid in DDD?
On the other hand, during our DDD implementation, we need to be careful of certain practices those are too common among software developers. These are:
1) Using a Data-Centric View When Modeling the Problem Domain
Usually, the data model is the first thing that an architect/developer would start to design. They always consider that data is the most important thing because data is all that we need to report. If you start with DDD, you must change this mindset. Data on its own is meaningless. Only logic gives data a meaning, and the same data can have a different meaning in different contexts. Therefore, we must start with context and logic instead of data.
2) Focusing on Implementation Details Like Entities, Value Objects, Services, Factories, and Repositories Instead of the Core Concepts
Entities, value objects, repositories, and so forth don’t have a meaning until we defined the ubiquitous language, bounded contexts, and the interfaces/crafted software contract. If we start to early with the implementation details like entities, then it’s a good chance that the result would be an anemic domain surrounded by a lot of services and business logic scattered everywhere.
3) Using Generic and Developer-Specific Terms and Concepts When Implementing the Application
We should never use concepts like save, update, delete, handle, manage, etc. Those concepts are too technical- abstract concepts with no specific meaning. Instead, we must stay focused on the business concepts. Those aforementioned concepts (i.e. save, update, etc) are not related to business concepts. To understand this, I encourage myself to always imagine the client running his errands/business without computers (doing specific tasks manually). So, always think from the business/domain expert perspective, and give a clear context on it. Avoid generic terms that can lead to different meanings in different, non-specific contexts.
4) Overrating DB Transactions Instead of Focusing on the Business Processes or Transactions
Within DDD, business transactions are more important than DB transactions. DB transactions are ACID, strongly consistent, and short running, while business transactions are not. In fact, in the real life, we don’t know about DB transactions, we just know about business transactions. For example, imagine when you are sitting in a restaurant and order some foods or beverages. Within the order transaction, realize it or not, there will be a process with some asynchronous tasks with many possible inconsistent state changes; by the end, all states will be consistent (eventually consistent). This blackbox process works, is scalable, and is widely acceptable to everyone. Therefore, with DDD, do not ever think about DB transactions. Instead, always think about the real world processes, such as actions (behaviors) and their possible outcomes, or how to compensate for the actions if failures occurs.
You don’t have to understand all the aforementioned points for now. I know that most application developers are not too familiar with the idioms and peculiarities of those concepts. Just keep reading for now, and hopefully, it will become clear when the other parts coming.
Read the next part here.