Domain Driven Design Cheat Sheet

admin February 22, 2026 5 min read 32 views
DDD
Domain Driven Design Cheat Sheet

Introduction

The goal of this blog-post is not to be a complete

Domain Driven Design is an approach to software development that centers the development on programming a domain model that has a rich understanding of the processes and rules of a domain.

How and why?

  • Think on a strategic level and tactical about your software
  • Tackle difficult business requests for now and in the future
  • Centralization of domain knowledge
  • Be really in control of your code-base

Phases of DDD

If you want to get really deep in domain driven design, I would invite you to check out the DDD Starter Modelling Process from the ddd-crew.
In the basis it comes down to eight steps. Honestly for most companies going through all of the steps in detail is a bit to much. So my advice would be to take and use whatever you need.

Understand — Align the team around the business model, user needs, and strategic goals before touching any design or code. Tools: Business Model Canvas.

Discover — Collaboratively explore the domain with domain experts and developers to build shared understanding. The most critical step and primary tool: EventStorming.

I have done this a few times now, and I love it how you can working together and form the landscape

https://github.com/SAP/curated-resources-for-domain-driven-design/blob/main/knowledgebase/tools/eventstorming.md
https://www.youtube.com/watch?v=1i6QYvYhlYQ&t=2698s https://github.com/mariuszgil/awesome-eventstorming

Decompose — Break the domain into loosely-coupled sub-domains to reduce cognitive load and identify natural boundaries for teams and architecture. Please keep in mind that is also a phase in where can you make tactical decisions for the business.

Strategize — Classify sub-domains to find your core domain — where you invest the most. Drives build vs. buy vs. outsource decisions. Tool: Core Domain Charts.

Connect — Design how sub-domains interact via messages, commands, and events to ensure end-to-end use cases work without tight coupling. Tool: Domain Message Flow Modelling.

Organise — Align team structure to the bounded contexts identified, optimising for autonomy and fast flow. Informed by Team Topologies and Context Maps.

https://github.com/ddd-crew/context-mapping

Define — Explicitly document each bounded context's responsibilities, language, rules, and interfaces before committing to code. Tool: Bounded Context Canvas.

When working on Bounded Contexts also check out context-mapping:
https://github.com/ddd-crew/context-mapping

Code — Implement the domain model in software, keeping code structure aligned to the domain. Tool: Aggregate Design Canvas.

source: https://github.com/ddd-crew/ddd-starter-modelling-process

Coding components

This paragraph emphasizes on the coding aspects of DDD. Its more like a summary of the different building blocks and how they are to be used.

Entities

Entities are regular objects with properties that form your domain model. All entities have a meaning in the context of your code, together with their properties. But some Entities are so important in your domain model, that all events in the software are directly related to certain objects and their state.

Entities. An entity is an object with a unique identity that persists over time. For example, in a banking application, customers and accounts would be entities.

An entity has a unique identifier in the system, which can be used to look up or retrieve the entity. That doesn't mean the identifier is always exposed directly to users. It could be a GUID or a primary key in a database.

An identity may span multiple bounded contexts and may endure beyond the lifetime of the application. For example, bank account numbers or government-issued IDs are not tied to the lifetime of a particular application.

The attributes of an entity may change over time. For example, a person's name or address might change, but they are still the same person.

An entity can hold references to other entities.

For example a Worksystem

Worksystem is an entity that has an ID, with all kinds of properties. An example of such a property, which is also an entity, is an instrument within a Worksystem.

These are the characteristics of an Entity
An Entity has an identifier (ID)
An Entity has an owner
An Entity can be mutable
An Entity has a thread of continuity

Aggregates

Some objects in software are more important than others. Some of these objects play a crucial part in the business process that your software tries to facilitate. We called these objects Entities (as discussed above).

However, some objects are not just normal entities. They are so important that all other objects are linked to them in some kind of way.

According to Microsoft: An aggregate defines a consistency boundary around one or more entities. Exactly one entity in an aggregate is the root. Lookup is done using the root entity's identifier. Any other entities in the aggregate are children of the root and are referenced by the following pointers from the root.

For example, we have a piece of software which is a car configurator.

We have in the software an entity called Car. The car entity has wheels and windows properties. Which are also entities.

Wheels and Windows have all kinds of other properties.

In the group of Cars, Wheels, and Windows, you can see a hierarchy forming.

We can't do anything in the software with only the wheels and the windows if we don't have the car. So the Car entity is really important. In this example, it's the object where it begins. It's the Aggregate. In the lifecycle of a Car Aggregate, it's the Car object which we also like to call the Aggregate root. In our software, everything begins with a car.

The window and the wheel objects are entities. Because they can change and also have unique IDs, but that's it. They can't live on their own in the software. Maybe in other situations? But not here.

The principal idea of Aggregates is that you need to cluster your entities in such a way that you can define boundaries around them.

Some design rules for forming an Aggregate

  • The software can have multiple Aggregates

  • Entities in the Aggregates can only change through the Aggregate-Root object.

  • When changing properties in the Aggregate, every change in state, has to be completed within a single transaction

  • Aggregates can have a reference to each other only by ID

  • Try to design Aggregates to be as small as you can, if you involve too many objects, unforeseen problems can occur when working on new features. The bigger it gets, the more complex it will be to work with it.

  • If you want to force a change outside the Aggregates, based on a change of state in the Aggregate, it needs to be done through integration events.

  • Try to avoid Dependency Injection into an Aggregate

Value Objects

A value object has no identity. It is defined only by the values of its attributes. Value objects are also immutable. To update a value object, you always create a new instance to replace the old one. Value objects can have methods that encapsulate domain logic, but those methods should have no side effects on the object's state. Typical examples of value objects include colours, dates and times, and currency values.

Factories

In DDD factories are responsible for constructing the complex object such as Aggregate. Sometimes to generate a complex object it needs to have additional information from external systems or data stores. So that means that factories can call outside systems (through adapters or repositories, etc) to gather the information/data that is needed to create the object.

When designing a factory:

  • make sure that all operations are atomic

  • make sure that you are careful in selecting your input parameters

Furthermore, sometimes you don't need an entire factory, you can use the constructor of the domain object, itself. When only to use the constructor

  • When the class is also the type

  • When the construction of the object has no complexity

  • The creation through the constructor must also be atomic

Events

To avoid using lots of complex domain services and tight coupling in DDD we need to use events to pass important information from one domain model to the other. In DDD we have 2 kinds of events. Domain events and integration events.

Domain events:

A domain event is something that happened in the domain that you want other parts of the same domain (in-process) to be aware of. The notified parts usually react somehow to the events.

  • Published and consumed within a single domain

  • Sent using an in-memory message bus

  • Can be processed synchronously or asynchronously

Integration events:

An integration event is used to propagate committed transactions and updates to additional subsystems, whether they are other micro-services, Bounded Contexts or even external applications. They should occur only if the entity is successfully persisted, otherwise, it's as if the entire operation never happened.

  • Consumed by other subsystems (microservices, Bounded Contexts)

  • Sent with a message broker over a queue

  • Processed completely asynchronously

It's important to understand that this event-based communication is not implemented directly within the aggregates; you need to implement domain event handlers. Handling the domain events is an application concern. The domain model layer should only focus on the domain logic—things that a domain expert would understand, not application infrastructure like handlers and side-effect persistence actions using repositories. Therefore, the application layer level is where you should have domain event handlers triggering actions when a domain event is raised.

Nice to know: Many DDD authors like Eric Evans and Vaughn Vernon advocate the rule that one transaction = one aggregate and therefore argue for eventual consistency across aggregates. However, other developers and architects like Jimmy Bogard are okay with spanning a single transaction across several aggregates—but only when those additional aggregates are related to side effects for the same original command.

https://lostechies.com/jimmybogard/2014/05/13/a-better-domain-events-pattern/https://lostechies.com/jimmybogard/2010/04/08/strengthening-your-domain-domain-events/

Sources

A gold mine for most of your DDD resrouces
https://github.com/ddd-crew

DDD Fundamentals

https://app.pluralsight.com/library/courses/fundamentals-domain-driven-design/table-of-contents

DDD in practice

https://app.pluralsight.com/library/courses/domain-driven-design-in-practice/
https://app.pluralsight.com/library/courses/fluentvalidation-fundamentals/table-of-contents
https://enterprisecraftsmanship.com/posts/always-valid-domain-model/

Event Storming

https://www.youtube.com/watch?v=1i6QYvYhlYQ&t=2698s
https://github.com/mariuszgil/awesome-eventstorming
https://allardschuurmans.nl/event-storming/

Context Mapping

https://www.youtube.com/watch?v=k5i4sP9q2Lk

Books

https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215 https://www.amazon.nl/-/en/Vernon-Vaughn/dp/0321834577