What is Domain-Driven Development?

By Ivan Knezevic, Software Architect at Authority Partners

First, let me establish what it is not.  

For one, it’s not a magic bullet of any kind. It is not a software’s architecture, nor is it a design pattern. And, it has nothing to do with a specific coding language or technology. It’s also not a set of instructions that you can just blindly follow.  

Domain-Driven Development (DDD) is simply a software development approach – a way of deconstructing a problem so it’s easier to solve. And it is A way, not THE way.  

Let’s take e-commerce as an example, as it’s one of the easier ones. The main purpose of e-commerce is to sell products online. So, you go and create a web shop, and put lots of stuff there. However, at some point, you decide you’d like to add a discount to some items, such as buy three get one free. Or maybe 20% off on orders of 5 or more items. And let’s add 10% off on orders above $100. But wait, let’s also add coupons… like for Black Friday. Then, you cram all of that in, somehow. And then you decide it would be cool to sell not just physical items, but also downloadable items such as e-books and software. Excellent. But the shipping address makes no sense now, and you must have a way of tracking who purchased what and providing a download link. And it’s starting to get more and more complex. 

Since your e-shop works with physical items, you need to actually ship those items. But before shipping you must bill the items, manage payments, manage physical inventory, supply chains, etc… Doesn’t seem so easy anymore, right?  

This is basically the inherent complexity of the real world. It goes much deeper than that, especially if you make it an international store, so you have to worry about compliances, customs, import/export taxes, and on and on.  

That whole complexity is what DDD is meant to help with. And yes, I’ve heard it said that DDD is intended only for large systems, but it’s more accurately to state it’s meant for complex systems. It doesn’t mean it can’t be used for smaller and less complex systems, however there is a big caveat: DDD is complex itself and takes a significant amount of effort and time to utilize properly, which makes it very expensive to use unless you actually need it. Overkill, in a way. Also, DDD is very difficult to use for domains that are more technical rather than business-oriented. Using it for what it’s intended for is so much more effective.

Strategic Design 

In DDD, we usually start with the big picture, more formally known as strategic design. Here, we’re concerned with questions of “what?” and “why?” What needs to happen, and why does it happen? The important part here is the domain, business domain to be more precise. For e-commerce, it would be online shopping, AKA selling products. For a logistics business, it would be shipping.  

So, as we start asking questions on what and why, we’ll start breaking the whole of the business domain into subdomains. Those subdomains can be core, supporting or generic subdomains. Core subdomains are what business is all about. They are the money makers.  

Product listing would be one such subdomain. Supporting domains contribute to and promote the core domains – they add extra values to it. Purchase reviews don’t bring money directly, but they definitely support purchasing indirectly. Finally, the generic subdomains are usually technical pieces that need to exist for the business to work, things like authorization subdomain, permissions subdomain and logging subdomain, etc. They don’t bring business value, but you still need them for the system to work.  

Subdomains have relationships with one another, and those relationships are described with context maps.  

The most important concept of subdomains is the bounded context. It is a logical boundary in which the terms are consistent, and the language used is called ubiquitous language. What that means is that, within that bounded context, terms are defined and immutable. Ideally, each subdomain is mapped to a single bounded context. In my opinion, ubiquitous language is the idea that can and should translate outside of DDD.  

Language is important. 

If I ask a software developer what DDD is, they’d probably answer with Domain-Driven Development. The same question asked to the pharmacist or doctor would give a completely different answer; DDD is a Defined Daily Dose.  

Same term – different meaning. And it’s near impossible to have a meaningful conversation between two or more parties if the language they use is different. That is why the bounded context is so important. Within that bounded context, a term always has one and only one meaning. Also importantly, one meaning can have different terms in different contexts.  

The whole idea behind Bounded Context is to help establish efficient and successful communication between developers and business stakeholders. Because the software design is driven by that business domain, knowledge of the domain is a must. Subdomains are often highly complex and always connected to other subdomains. It’s almost guaranteed that you, as a software developer, will not be overly familiar with the actual subdomain.  

If I asked a developer to create a filing system for the Ministry of Justice, where would they start? What would be the scope of the system? In order to figure that out, the developer would go and talk to different people in the Ministry – clerks, lawyers, judges, assistants, etc. And soon, the developer would discover that, while there is a lot of overlap, which we call a Shared Kernel, all those people have different ideas about what the most important part of the system should be. They would also use the same terms but with different meanings.  

For a lawyer, a filing is something they create and submit to the records. A lawyer would keep that document attached to the client file, because at the moment they’re creating those filings, there is no record ID for it in the system.  

For a judge, it’s a document to be read, and it would be attached to the case record with a record ID, that their hearing. Also, the judge doesn’t have clients, but there is a defendant. ’. It is in fact much more complicated, but you get the idea. 

For a clerk, a filing is a cabinet where the documents are stored, and not the document itself.  

As you can see, each of these people care about different things. They have different ideas about what’s needed, and how things should work. And they use different language.  

Again, bounded context is a boundary where the language is ubiquitous. Within that bounded context, every term always has the same meaning. In one bounded context, a client means a person paying the bills, and within that bounded context that’s always the case. In a different bounded context, a client would mean a person being represented in the court of law. In a third, it’s an application or a system connected to our own system.  

I cannot emphasize this enough: Establishing ubiquitous language, and thus bounded context, is paramount! Without proper communication, it’s very difficult to talk about what the system needs to do. The end goal is to have Business and Development aligned.  

All that we talked about so far was the strategic design of DDD.  

Tactical Design 

While strategic design is the big picture stuff, tactical design is more concerned with the question of “how?” The focus here is on the scope and implementation details.  

In DDD code base, each domain object is either an entity or a value object. An entity has an ID and properties. An entity is mutable. A product in e-commerce would be an entity, for example. Two entities are also equal if they have the same ID, even if their property values are for some reason different.  

A value object on the other hand doesn’t have the ID. It’s defined by its values and two value objects are equal only if all their property values are equal. They are also immutable. An example of such value object would be a simple e-mail address.  

Strings, integers, floats or Enums are NOT valid objects in DDD. They can be used as property values, of course, but they are not valid objects. Things like e-mail, price and address are domain value objects, not values by themselves.  

One or more domain objects that always need to be consistent are called an aggregate. The entity that’s at the root of that aggregate is an aggregate root. That entity has a responsibility to keep the aggregate in a valid business state. We’re not talking here about input validation and such, but business validation. For example, if a business rule states an order with three or more items must have a 5% discount applied to the total order price, then that needs to be validated and applied on any change within the order aggregate.  

From this, it simply emerges that an aggregate is also a transactional boundary. All changes to an aggregate are either committed or rolled back as a whole, to keep the aggregate in a valid state.  

There is a lot more to talk about DDD, but this should be the very basics to help people start. Consider the benefits and downsides, and make the choice yourself. Finally, there are a lot of ideas from DDD (such as ubiquitous language and value objects) that can be used in non-DDD approaches.  

I hope this was helpful and see you around.  

To summarize:  

DDD is a software development approach (for designing complex businesses). Start with strategic design: What? Why? The focus is on the big picture stuff.  

Find all subdomains that the business domain has:  

  • core (what the business is all about, what brings in the money)  
  • supporting (supports the core subdomain, adds additional values to it)  
  • generic (logging, auth, permissions, etc. needed to make it all work as a system)  
 

Subdomains have relationships to one another, which can be described with context maps. Ideally, each subdomain is mapped to a single bounded context.  

Bounded context is a logical boundary in which the terms are consistent. Language used within the bounded context is called ubiquitous language.  

Tactical design: How? The focus is on the scope, implementation and solution details.  

In a DDD code base, each domain object is either an entity or value object.  

  • Entity has an ID, and two entities are equal if and only if they have the same ID (even if their values are different for some reason). Entities are mutable.  
  • Value objects don’t have an ID, and two value objects are equal if all their values/properties are equal. Value objects are immutable.  

One or more domain object that always needs to be consistent is called an aggregate. The entity that is the root of an aggregate is called an aggregate root.  

The aggregate root responsibility is to ensure the entire aggregate is always in a valid (data? and business) state.  

An aggregate is also a transactional boundary, which means any changes to it are either committed or rolled back as a whole. That helps with keeping the aggregate in a valid state. 

 

Ready to elevate your project with Domain-Driven Development? Reach out to us at hello@authoritypartners.com and let’s make complexity manageable together. Discover more by filling out this form and kick start your journey to streamlined software success.