Should you be applying domain-driven design? Do you need a domain model? You might want to if you have a lot of complexity within your domain. I often get asked, “what is a lot of complexity?”. I’m going to provide an example by uncovering more and more complexity within a domain. And give a few different insights that should help you make the decision.
Check out my YouTube channel, where I post all kinds of content accompanying my posts, including this video showing everything in this post.
Through this post, I’m going to illustrate an example using a shipment, moving freight/goods from one location to another. Everyone should be able to relate to this. You order something online and have it delivered to you.
Let’s start with the simplest form. First, a vehicle will arrive at the first stop, often called the shipper, and pick up the freight.
Then the vehicle will drive to the destination, often called the consignee, and deliver the freight.
When considering an order you place online, this would mean a vehicle goes and picks up your order/package at a warehouse or store, then delivers it to your house/apartment.
On the surface, the complexity within this domain model might seem minimal. A shipment will be associated with a vehicle, pickup, and delivery location. In terms of behaviors, we would be able to arrive at the pickup location, pick up the freight, depart the pickup location, arrive at the delivery location, and deliver.
This is pretty simple at this point in terms of our conceptual model. In terms of domain logic, it would be around making sure we arrive at our pickup location before we arrive at the delivery. This means we are doing shipment steps in the correct order.
As we dig into the reality of this domain, the complexity within this domain model is about to go up drastically. A vehicle isn’t always going to pick up a single package and bring it directly to the delivery location. What may also occur is bringing the shipment to a warehouse before the final delivery.
This means that Vehicle A might pick up the freight from our pickup location and then deliver it to a warehouse or some intermediate location.
The freight might sit at this warehouse location for a period of time.
Finally, when the product needs to move to the delivery location, we could have Vehicle B arrive at the warehouse to pick up the freight.
Vehicle B then drives to our delivery location to deliver the freight to the final destination.
We’ve added a bit more complexity. Now we need to keep track of which vehicles are involved in our shipment.
Now with this model, we could have many intermediate pickups and deliveries as needed. For example, we may have two different warehouses involved before our final destination.
Now let’s say that we have a shipment that the freight is split into multiple packages that need to be delivered to multiple locations.
First, the vehicle picks up multiple packages at the pickup location.
It then brings the freight to the first delivery location and delivers one of the packages.
Then it drives to the other delivery location to deliver the final package.
Now, we need to keep track of the freight itself to determine which delivery location it belongs to.
Complexity. It never ends.
Let’s combine those last two examples: a warehouse or intermediate stop and multiple delivery locations.
Now depending on the size of freight and the types of vehicles, it’s not very efficient to have one shipment per vehicle. So this means that we have multiple shipments on a vehicle. And those individual shipments may have multiple pickup and delivery locations.
Is this starting to sound complex yet? Modeling the data might not be the most challenging part. However, all the business logic of making sure you’re routing these stops in the most efficient order, making sure you’re going to be on on-time for pickup and delivery times required, can get incredibly complex.
The reality of this domain has a lot of complexity that I’m just scratching the surface of. The point is that what looks pretty simplistic on the surface of a single package with a single pickup location and delivery location, in reality, goes much deeper and has a lot of complexity you need to manage.
What’s enough Complexity?
Do you warrant a domain model to manage the complexity? Here are a few questions to ask yourself.
Is it CRUD (create, read, update, delete)? Honestly, is it CRUD? When you’re working with a system that’s primarily CRUD, all of the workflow and business processes are in the end-users heads. They are the ones executing the workflow and entering the various pieces of data. They decide if X happens, then they need to input data into Y. The end user understands the workflow, not the software.
If you’re building a system that captures the workflow and will contain all that business logic, then yes, creating a domain model can be very beneficial as a way of organizing all that logic and complexity.
How many capabilities does your system provide? If you’re trying to decide if you should capture the workflow in your software, how many capabilities does it need to provide? If it’s minimal, it might not be needed.
If it is very limited, will it grow? Will the number of capabilities grow over time? It may start very small, but as its value is realized, more and more features are added.
The example I gave at the beginning may be the 80% use case. In that case, maybe you don’t need a domain model. But you do for the other 20%, which has a lot more complexity.
Not all models need to solve all the problems.
If you don’t know if you have a lot of complexity, then you don’t know enough about the domain and the problem the system is trying to solve. If this is the case, explore more about the domain, the problem space, and what it is you’re trying to solve.
Developer-level members of my YouTube channel or Patreon get access to a private Discord server to chat with other developers about Software Architecture and Design and access to source code for any working demo application I post on my blog or YouTube. Check out my Patreon or YouTube Membership for more info.
- CRUD API + Complexity = Death by a 1000 Papercuts
- Highly COHESIVE Software Design to tame Complexity
- Domain-Driven Design patterns for a distributed system