Domain-Driven Design is an approach to software development that connects the needs of the business to the implementation. I recently attended an “Implementing Domain-Driven Design” course by Vaughn Vernon. I highly recommend the course, and this is a summary of some of the high-level design tools we studied.
Throughout this post, I’ll describe how you might start with the fictitious scenario of an auction site for classic cars (which gives me a nice excuse to put a picture here!).
You might start with scenario mapping. Take a problem you need to solve and start to break it down into various scenarios. For example, imagine I’m writing an auction site for classic cars. One scenario might be two people competing for a highly sought-after car. What should the behaviour be? Working with your domain expert you’ll work through the scenario and flesh out the details. You might capture these details using a BDD style format.
Scenario: Possible fraudulent bid
Given that Jo has registered with a credit card
When Jo bids more than 100K
Then a hold should be placed on the credit card
The point here isn’t the detail of this particular scenario, and it’s certainly not about getting any code implemented, it’s all about knowledge acquisition (one of the four types of work in Scrum alongside features, bugs and technical work).
We’re going to start with a process known as event storming. Event storming is a group activity to model and understand the domain of a system. In event storming you understand a scenario from time started to time finish. You start by breaking it down into a series of domain events. Events state facts that happens (“New Auction Added”, “Car Auction Completed”). These events are known as domain events and they should be things that have real meaning to a domain expert (e.g. not something like “For Loop Completed”!).
You might find you have business process that needs to occur after an event. For example, in our domain before we can add a new bid, we need to understand whether the client can meet that bid (we might do a credit hold). We try not to go into the details in the first instance, and just mark this as a “business process” to revisit later.
Similarly, we might find we have commands. These are actions taken by an actor on the system. For example, the auctioneer (the Actor) might close the auction early (a Command).
Each command is associated with an aggregate. An aggregate is a set of domain objects that can be treated as a single unit. For example, Auction — Car — Bid might represent an Aggregate. They are a cluster of domain objects that change together. However, users and accounts would not be part of the same aggregate.
Throughout the event storming process, we’re deepening our learning. We’re identifying areas of business logic that need further investigation (business process), business events and domain objects.
Now we’ve got an understanding of the domain we can start mapping it into domains and sub-domains. We’ve already identified a couple for our car scenario Auction/Car/Bid represents the Auction sub-domain and Accounts represents the users of the system.
These subsystems represent a sub-domain (a problem space all its own). Each problem space should be 1:1 represented by a solution space (known as a bounded context). Each bounded context has a ubiquitous language where each concept makes sense and is unambiguous. For example, in the auction sub-domain Car is clearly referring to the car we’re auctioneering, whereas in the user profile it might refer to their dream car.
Each bounded context should ideally be worked on by one team. Why’s that? Well, it gives a clear mandate for the team and removes ambiguity.
Bounded contexts are integrated by context mapping. Context mapping is a high-level abstraction that allows you to model how contexts communicate. For example, you might say that Auctions and Accounts are in a supplier/consumer relationship (Accounts exist to serve Auctions). Accounts might not be core to your business, so Accounts might be a supplier to you, in which case you have a different relationship. Time to market might be important so you put two teams in a partnership on Auctions. This is OK, but it has trade-offs. Context mapping helps you understand those trade-offs.
Context-mapping is a powerful tool for mapping out not only your high-level architecture, but also the team structure underneath.
That’s my whistle-stop tour of high-level design tools in DDD. In the next episode of this series, we’ll look at how these map to the architecture and that’s really where the strength of DDD comes in. Your domain model, implementation and team structure are strongly connected throughout the process.