03 Domain Driven Design
A software development approach born out of the XP programming world, carrying with it all the OO concepts from UML, and focuses on modelling the problem domain within which a software system operates. It’s a continuation of the good works of Ivor Jacobson (Use Case Modelling) and Rebecca Wirfs-Brock CRC Cards and Modelling.
Domain - Focus on developing a deep understanding of the domain in which the software system will exist. The domain model should encompass the real-world concepts, rules, and processes that the software is intended to model or support. The logical modelling of tech Block 2 represents a part of this modelling.
Driven - Everything you do is guided by that domain knowledge and understanding. Avoid being driven solely by technical issues. It’s domain-driven first, technically driven second
Design - Step back from the edge of going straight into the code, create some kind of blueprint, and then incrementally build out the applications(s).
The two primary concepts are
Strategic Design - defining the architecture of a software system in a way that aligns with the problem domain. It addresses high-level concerns such as domain concepts, partitioning the system into manageable parts, and defining the boundaries between those different parts once the system has been partitioned
Tactical Design - these are patterns that encompass specific strategies or techniques used to realize domain model elements within a software system. These patterns are well established in the software industry and help developers effectively capture the complexity of the domain, whilst promoting maintainability, flexibility, reusability, scalability etc.
01 Domain Knowledge
I’ve always said, “Customers pretty much know what they want but struggle to articulate it, when you show them something, then the light bulb goes on and their directing becomes a lot clearer”.
Steve Jobs famously said “Some people say give the customers what they want, but that's not my approach. Our job is to figure out what they're going to want before they do. I think Henry Ford once said, 'If I'd ask customers what they wanted, they would've told me a faster horse.' People don't know what they want until you show it to them. That's why I never rely on market research. Our task is to read things that are not yet on the page.”
Read this interesting article.
Market research is important but don’t let it stop your drive towards visionary solutions. If you do, then innovation will cease.
02 Strategic Design
Defining the architecture of a software system in a way that aligns with the problem domain. It addresses high-level concerns such as domain concepts, partitioning the system into manageable parts, and defining the boundaries between those different parts once the system has been partitioned
Centres around 6 principles
Bounded Context *
Context Mappings *
Strategic Patterns *
Shared Kernal *
Anti-Corruption Level
Ubiquitous Language
02-01 Bounded Context
Large systems are notoriously complex and difficult to maintain and manage, as we saw when we played with the VAT calculator application. By breaking large systems into smaller pieces it becomes easier to develop, manage, and deploy, but there is a cost associated with this. We discuss this later.
Consider the timesheet example you saw earlier in the programme
Here we ring-fenced each area of concern, and we labelled them Domain 1, 2, and 3. Our focus for this discussion is the data but it could be software components or hardware components.
As can be seen from the updated diagram, Timesheet Info (a tab in a spreadsheet) becomes Work-Project-Info (some data in a project time management system) becomes Timesheet Acc Info (a type in an accounting system).
If you were to have a discussion with SMEs within each of these domains, you would very quickly learn that they all use a different term for the same thing. Is one term better or more accurate than the other? No, that’s the wrong way to think about it. Each term is valid within its context (the bounded context).
02-02 Context Mapping
Each bounded context encapsulates the language, concepts, and processes for the domain that it represents. This is a great idea, but when you have to wire the domains back together the system becomes a spaghetti of code. A RPC style approach to wiring things together is very messy, a better approach is to use some kind of service bus, a MOM.
Whether you use a RPC or MOM style architecture context mapping has to occur between each domain (bounded context). So the models above would be redrawn as shown below,
There are pros and cons for both approaches. With the RPC approach the mapping tables are much smaller and tailored specifically towards an individual pair of dependencies. With the MOM approach, you could end up with a single Context Mapper trying to be all things to all Domains. A far better approach would be to create smaller mapping contexts that only listen for certain events.
02-03 Strategic Patterns
Examples of strategic patterns
Aggregates
Domain Events *
Anti-Corruption Layer
02-03.01 Domain Events
If we talk about events, then we need to talk about states.
States
Transitions
The duality of states and events
Some Notation (UML State Modelling - Harel’s Machines)
We can use Harel’s Notation to help us capture the duality of states and events
This model represents the lifecycle of an email application
This model represents the lifecycle of a bank account
You can see that we have used the same notation to model different levels of complexity and abstractions.
02-03.02 Event Sourcing
Consider an e-commerce system. Instead of storing the current order details, you’d store a series of events like ProductAdded
, QuantityUpdated
, and OrderPlaced
. To retrieve the current order, you'd replay these events from the beginning.
02-04 Shared Kernel (strategic pattern)
Consider the model below, it’s an extract from the hotel example you worked on during Tech Block 2. The <<domain>> stereotype signifies an area/function of the business.
There are two processes that we want to consider, making a reservation using an online application, and creating the bill when a client checks out of the hotel. The current model (the one above) uses a none DDD approach. Classes are defined in one domain and reused across other domains. This is NOT the DDD philosophy.
Following DDD we could create a shared context called the Billing Context.
This shared kernel pattern facilitates collaboration and integration between contexts whilst allowing each context to maintain its distinct model. This pattern should be used judiciously. And overuse of it can lead to increased dependencies between contexts which ultimately lead to tight coupling.
QL-01 Creating Bounded Context and Context Maps
Using the Hotel Case Study, develop the
Bonded Contexts
Context Maps
Shared Kernels if you think they exist
List the significant events in each context
Define a event sourcing table for one of the triggering events
03 Tactical Design
Tactical design patterns are specific strategies or techniques used to structure and organize the domain model within a software system. These patterns help developers effectively capture the complexity of the domain, while also promoting maintainability, flexibility, and scalability.
The important thing to remember about this phase in DDD is that it’s focused on arming the software developer with the tools they need to implement a software system following DDD approach.
These patterns are
Entity
Value Object
Aggregate
Repository
Factory
Service
03-01 Entity Tactical Design
Example
In a banking application, a Bank Account (something that has meaning to the business) might have properties like account number, possibly its balance as this can be derived by summing the transactions against the account, date opened, and last accessed, along with methods to deposit, withdraw, or transfer funds, as well as other useful methods.
03-02 Value Object Tactical Design
03-03 Aggregate Tactical Design
03-04 Repository Tactical Design
This model is all about enforcing the separation of concerns. Entity and Value objects have no idea what underlying technology is being used to manage their persistence.
03-05 Factory Tactical Design
03-06 Service Tactical Design
And the behaviour of the service class (Account Owner Service) would look something like this