Using Domain-Driven Design
May 24, 2019
Design – It’s Everyone’s Job
Design is a word with many meanings in the software development industry. From user-experience design, where the focus is on designing products for ease of use, to system design, where the focus is primarily on efficiency and resiliency. Though different in practice, all types of design in the software world have one common goal: to provide a great experience for the end user. This is a multifaceted challenge that involves many individuals with different skill sets working to address new complexities around every corner. Usually the biggest challenge is the business domain itself.
There are very few software developers who are financial industry gurus, and vice-versa, so collaboration between developers and business area experts is key when working within such complex business domains. However, the typical operational model used by most software development teams of “let the business analyst write the acceptance criteria, and let the developers focus on the code” drastically limits collaboration, leaving the overall system design up to the developers, who have a limited understanding of the business itself. This often leads to products that don’t fully meet the business’s needs.
A good system design is one that the entire team collaborates on throughout the entire lifetime of the project, but an alternative approach is the use of a time-tested software design methodology called Domain-Driven Design (DDD).
What Is Domain-Driven Design?
DDD is a software design methodology used when designing software for complex business domains. It’s the idea that software should be based on models that reflect the subject area in which the software is for, otherwise known as the domain. Creating these models is a process known as domain modeling, which is the backbone to DDD. Once defined, the domain model serves as the underlying foundation of the software, and as a shared language that will be used across the team to unify communication between business domain experts and developers.
Communication is the most challenging aspect of working on a project with team members from different backgrounds. Business experts usually describe concepts differently than software experts, and sometimes even team members with the same background describe things completely differently. If a team can avoid having to translate conceptual details between team members, then the team’s efficiency and productivity skyrockets, and the opportunity for collaboration increases exponentially.
One of the main purposes of using DDD is to provide teams with a commonly shared language based off the domain model. This model-based language is meant to be used when discussing any aspect of the project, and the same terminology should be reflected in the code. At first it may be challenging, but the value of eliminating inconsistencies in communication proves the challenge is worth accepting.
The Art of Domain Modeling
Effective domain models are meant to be constantly refined and changed through every iteration of a project. It’s a collaborative effort that requires consistency and attention to detail from every team member involved on a project.
Let’s use a real-world example to get a hands-on feel for defining a domain model. Keep in mind that domain models are defined conceptually. There isn’t a specific diagram or document format used to define the model. The decision on how the model will be documented is up to the team. Some teams rely only on the code to define the model, where other teams may use a UML diagram as well as code to define the model. For this article we’re just going to define the model in plain text, but before we start defining the model, let’s first start by defining a few key technical concepts to think about when building domain models.
- Domain – The subject area that to which all subdomains, entities, behaviors, and operations belong.
- Subdomains – All logically specific areas of the greater domain.
- Bounded Context – The logical boundaries between subdomains.
- Aggregate Roots – A subdomain’s interface that other subdomains use to reference exposed parts of a subdomain.
Now let’s define a domain model. Let’s say we were given requirements to build an application that will allow home owners to order home repair services from a list of qualified service providers. The first step to defining a domain model is determining the domain itself. For our example, the domain is “ordering home repair services.”
The second step is breaking the domain out into subdomains. The easiest way to do this to think in terms of contexts, or areas of specific logic within the greater domain. Let’s apply this to what we know about our requirements. At a minimum, we know a home owner will need to be able to order repair services, and service providers will need to be able to see what orders have been placed. From that, we see that there will need to be at least two types of users (home owners and service providers), and we see that orders behave differently for each type of user. So for our example, the subdomains are Account Management Context, Home Owner Orders Context and Service Provider Orders Context.
The next step is to define the bounded contexts for each of these subdomains. Properly defined bounded contexts ensure that all subdomains are only responsible for the things they should be. For the sake of brevity, I’m not going to list all operations and behaviors for each subdomain, but an example would be that the account management context wouldn’t have access to any order information or logic, since the account management context is only responsible for managing user accounts.
The last thing we will need to define for our domain model to be complete is the aggregate root of each bounded context. Think of this as how parts of one subdomain interact with the parts of other subdomains. For our example, the aggregate root of the Account Management Context would be the user domain object, Home Owner Orders Context would be the order domain object, and the Service Provider Orders Context would be a different order domain object. At first, this might seem too technical for business area experts to care about, but knowing how each subdomain interacts with the other is imperative for influencing decisions on the design of the system.
In practice, there’s much more effort and collaboration involved in domain modeling. The model should be defined as a team, and it’s the entire team’s responsibility to keep the model consistent. If defined properly and kept consistent, the value that comes from a good model will outweigh the extra effort that it took to define it tenfold. It is important to remember that the domain model is the single most important piece of any DDD project. It is how the code will be organized and written, and it’s how the team will communicate.
Pros and Cons
It is worth noting that all projects aren’t suited for DDD. If a team already has a solid understanding of the fundamentals of the problem domain, then DDD may be unnecessary for that project. DDD can be time consuming, and it requires having resources on the team that are business domain experts. However, when developing solutions catered for highly specific business domains there isn’t a better approach.
At CoreLogic, we leverage DDD to incorporate our industry leading expertise in the products we provide. DDD is also a great complement for iterative software development processes such as Agile, and by relying heavily on object-oriented principles, it increases modularity, which leads to more flexibility within a system’s design. In short, Domain-Driven Design increases knowledge and collaboration across team members and supplies teams with a set of practices that ensures unrivaled quality and efficiency in the products being delivered.
Written by Jon Underwood, Professional, Software Engineer