Skip to main content

Command Palette

Search for a command to run...

Domain Driven Design Introduction

Updated
9 min read
Domain Driven Design Introduction
H

Welcome to my blog. I'm Duy Hieu, Senior Software Engineer at FPT Software. I created this blog to share my stories.

I. Why DDD matters? A Bigger Picture

Over the years, as business needs have grown increasingly complex, our application systems have evolved - from monoliths to SOA, and now to microservices. This evolution demands a rational approach to component decomposition and integration.

Many companies, including the one where I previously worked, have experienced systems ballooning over time due to improper decomposition, leading to tightly coupled data and components. This often leads to problems such as domain leaks, inconsistent data, overly large codebases, and frequent system failures.

Source: https://medium.com/startlovingyourself

Domain-Driven Design (DDD) emerges as a systematic approach for large-scale projects with complex domains. By promoting clear boundaries between subdomains and a shared language between business and technical teams, DDD helps to avoid the pitfalls of past systems. It ensures every component is self-contained, with clearly defined responsibilities that accurately represent the specific business processes they support.

II. What is DDD?

Domain Driven Design (DDD) is a development philosophy defined by Eric Evans in his seminal work Domain‐Driven Design: Tackling Complexity in the Heart of Software (Addison‐Wesley Professional, 2003).

DDD is an approach to software development that enables teams to effectively manage the construction and maintenance of software for complex problem domains. The main idea is splitting out the whole business domain into subdomains and microservices correspond to these subdomains.

For example, in designing a logistics system, you might divide the domain into subdomains such as Order, Warehouse management, Shipment, Routing, Address,…

Importantly, DDD can be applied to both monolithic and microservices architectures.

III. Step-by-Step DDD Process

DDD is very difficult to start, especially for newcomers. The DDD books are quite academic and verbose, which can be overwhelming. Therefore, I have summarized it into a 5-step process to help those new to DDD practice it as easily as possible. This guide takes you from understanding the requirements all the way to being ready for coding.

1. Identify problem space and business domain

1.1. Do assessment

Start by asking

  • What business problem am I trying to solve?

  • Who are the primary users of the system?

  • Is this project a new system or a legacy migration?

  • What parts of the current system should be preserved, and what needs to be rebuilt?

  • Which parties need to be integrated?

  • What pain points exist with the current system?

  • What is the project’s goals, timeline and budget?

This is a very important step. A wrong scope or a misunderstanding of resource constraints can lead to many consequences - redesign, rework, missed deadlines - and can also diminish the organization's credibility with its customers (especially in outsourcing).

Let's clarify the goal, timeline, and budget very carefully with the customers or your boss, because you will need to adjust the design to fit these constraints.

1.2. Talk to the domain experts/BA

We must involve people who know the business well - Product Owners, BA, managers - to get real insights and confirmation. Remember: Never Assume!

2. Build a Ubiquitous Language

Ubiquitous Language is a shared vocabulary between domain experts and developers. It ensures every term used in the code, documentation, and conversations accurately reflects business concepts.

Example (Online Store System):

Terms like Product, SKU, Category, Cart, Order, Checkout, Support Ticket,… should have precise definitions, ensuring clear communication between domain experts and developers.

TermDefinitionNotes/Examples
ProductAn item or service offered for sale in the system, with detailed attributes such as name, description, price, and images.E.g., a smartphone, a computer
SKUStock Keeping Unit – a unique identifier for a specific product variant used for inventory tracking and sales managementEach color/size variant may have a different SKU
CategoryA classification that groups similar products together based on shared characteristics or type, facilitating browsing and organization.E.g., Electronics, Clothing, Home Appliances

Best Practices for Shaping the Language

  • At the beginning of a project, we should create a dictionary of domain terms.

  • Ensure that you use one word for a specific concept. Don’t let the domain expert or developers have two words for something.

  • If you are using a term in code that the domain expert doesn’t say, you need to check it with them.

  • The business may use some terms proving to be too generic. The development team and domain experts need to create new terms and explicitly define the meaning of existing terms to implement the model in code.

3. Subdomain Decomposition

There are two common decomposition methods: by business capabilities and by Event Storming workshop.

3.1. Business Capability Decomposition

A business capability is a service (without the aid of technologies) that generates business values to a(n) business/company/organization as well as end users.

For example, the business capabilities of an online store include:

  • Product catalog management

  • Inventory management

  • Order management

  • Delivery management

  • Customer Service

To identify business capabilities, we should focus on the organization’s purpose, structure, and processes. Different groups/departments within an organization might correspond to business capabilities or business capability groups.

This method is especially useful for large companies with clear, established organizational structures.

3.2. Event Storming Workshop

This approach begins by running an Event Storming workshop to map out all the key events, commands, and processes from start to finish. You can watch this video guide to learn more about Event Storming in detail. In short, there are three workshop types in EventStorming:

  • Big Picture: visualizes the entire business landscape by identifying key events, actors and interactions to establish a shared, high-level understanding

  • Process Modeling: dive into specific business flows that are separated from Big Picture

  • Software Design: transform events from Process Modeling into concrete software designs (Aggregate, Entity, Value Object,…)

There are also a few main concepts that you need to remember:

To decompose subdomains, we only need to create a Big Picture. Below is a sample Big Picture for our online store system, where I identified all domain events arranged sequentially from start to finish.

By visualizing the business flow end to end, you not only gain a deeper understanding of how the domain operates, but you also reveal natural boundaries between subdomains. Once these boundaries become clear, you can decompose the system into distinct subdomains that reflect different parts of the business process.

After identifying these subdomains through Event Storming, you can classify them into three main types:

  • Core - key differentiator for the business and the most valuable part of the application.

  • Supporting - related to what the business does but not a differentiator. These can be implemented in-house or outsourced.

  • Generic - not specific to the business and are ideally implemented using third-party solutions.

For example, the subdomains of an online store include:

  • Core: Product Catalog, Order Management, Customer Service

    → they offer differentiates your business in the market and becomes a key driver of customer loyalty and competitive advantage.

  • Supporting: Inventory Management, Payment, Promotion

    → they are essential to operations but do not, by themselves, provide a unique competitive edge.

  • Generic: Delivery Management, Notification,…

    → many businesses can rely on established third-party logistics solutions for delivery.

This method is ideal for smaller organizations that don’t have rigid business structures but can be applied to any organization to any extent.

4. Identify Context Map

After identifying subdomains, we build Context Mapping - represents the relationships among bounded contexts (upstream, downstream, dependencies…).

Source: contextmapper.org/docs/examples

There are four common patterns:

  • Upstream/Downstream Relationship

  • Anticorruption Layer: a layer for integration, only contains translation logic, not business logic. We use this layer to integrate with code we don’t own or can’t change.

  • Shared Kernel: uses a shared model for 2 bounded contexts (have a lot of crossover in terms of domain concepts and logic). 2 bounded contexts can be in the same subdomain

  • Open Host Service: reduce duplication of ACL by exposing an API to be reused by many contexts.

However, after trying to draw context maps based on these patterns, I found them to be quite complex and hard to understand - especially as the number of bounded contexts increases. So, I simplified the approach by using just one type of upstream/downstream relationship, but divided it into two categories:

  • Synchronous integration via API

  • Asynchronous integration via events

By this way, everyone attending the workshop, especially the business team, can understand it easily.

5. Identify DDD Artifacts

Below are the key domain concepts that serve as the fundamental building blocks for our design after subdomain decomposition.

  • Aggregate: a group of related objects and treated as a single unit. It has an aggregate root that controls access to other objects. Only the root can be referenced from outside the aggregate

  • Aggregate Root: a central entity - entry point for a aggregate, all other entities are accessed only via root

  • Entity: a domain object that have a distinct identity

  • Value Object: an object that contains data but don't have an identity

  • Domain Event: An event that captures a significant change within the domain and notifies other components of the system

  • Domain rules: business logic and constraints that govern the behavior of the domain

  • Domain service: services/module encapsulate the domain logic that does not naturally fit within an entity/aggregate. Domain services use entities, value objects, or other domain services to execute domain-specific operations

Additionally, you can define domain operations (Queries and Commands) and long-running transactions (Sagas) that coordinate processes spanning multiple aggregates.

Example: Order Management Subdomain

  • Aggregate root: Order

  • Value Object: OrderItem, ShippingAddress, PaymentDetails,….

  • Domain Event: OrderPlaced, OrderCancelled, OrderDelivered,…

  • Domain Service: OrderValidationService (validate that the order details, check for inventory availability,… that does not fit within only Order Aggregate).

IV. Pros and Cons of DDD

DDD is not a silver bullet. Below are its benefits and drawbacks to help determine when it’s the right approach:

Advantages

  • Enables teams to manage complex problem domains using a divide-and-conquer approach

  • Encourages close collaboration between technical team and domain experts to ensure the software reflects real-world business processes

  • Establishes clear domain boundaries, making it easier to update or replace system components without affecting others

  • Avoid domain leaks between components, especially in microservices

Disadvantages

  • Can be complex for developers to fully understand and implement

  • Slower initial progress

  • Requires continuous refinement of the domain model

  • Offers less value for small or CRUD projects

Use cases

  • Large enterprise systems with complex domains such as banking, insurance, healthcare, or logistics,…

  • Microservices Architectures where each service aligns with a specific subdomain or business capability

V. Conclusion

Phew… We've covered the key concepts of DDD along with best practices for implementation. There's so much I'd like to include in this article, but I'm concerned it might be overwhelming. Therefore, I've focused on introducing the basic concepts and best practices, leaving additional details for you to explore if you're interested.

Once again, I hope this helps everyone get a good start with DDD and be ready to handle larger projects.

VI. References