2 minute read

2 min read 584 words

1. Introduction

When building simple CRUD (Create, Read, Update, Delete) applications, standard patterns are usually enough. However, when the business logic becomes complex, a technical-focused approach often leads to “anemic domain models” and brittle code.

Domain-Driven Design (DDD) is an approach to software development that focuses on the core domain and its logic, rather than technical implementation details. It aims to bridge the gap between business experts and developers.


2. Strategic Patterns: Ubiquitous Language

One of the most powerful concepts in DDD is the Ubiquitous Language. This means using the exact same terminology in the code as the business stakeholders use in their meetings.

If the business calls it a “Policy,” don’t call it an “InsuranceAgreement” in your code. This reduces translation errors and makes the system easier to reason about for everyone.


3. Tactical Patterns: The Building Blocks

DDD provides several “building blocks” to organize your domain logic:

1. Entities

Objects that have a unique identity that persists over time (e.g., a User with an Id). Even if their attributes change, they are still the same object.

2. Value Objects

Objects that have no identity and are defined solely by their attributes (e.g., an Address or Money). Two Money objects with the same amount and currency are considered equal.

  • Rule: Value Objects should always be immutable.

3. Aggregates

A cluster of domain objects that can be treated as a single unit. Every Aggregate has an Aggregate Root (an Entity).

  • Rule: External objects can only hold references to the Aggregate Root, not the internal members. This ensures data integrity.

4. DDD in .NET

In a .NET Clean Architecture project, your DDD building blocks live in the Domain Layer.

// Example Value Object
public record Address(string Street, string City, string ZipCode);

// Example Entity / Aggregate Root
public class Order : Entity
{
    public Guid Id { get; private set; }
    public Address ShippingAddress { get; private set; }
    private readonly List<OrderItem> _items = new();
    public IReadOnlyCollection<OrderItem> Items => _items.AsReadOnly();

    public void AddItem(Product product, int quantity)
    {
        // Business logic and validation here
        _items.Add(new OrderItem(product, quantity));
    }
}

5. When NOT to use DDD

DDD is a heavy-duty tool. Avoid it for:

  • Simple data entry applications.
  • Small prototypes.
  • Projects where the business logic is trivial.

Use it for: Complex domains where the cost of misunderstanding business rules is high (e.g., Banking, Healthcare, Logistics).


6. Conclusion

DDD is about shifting your focus from “how to store data” to “how the business works.” By using Ubiquitous Language and protecting your invariants with Aggregates, you build systems that aren’t just technically sound, but also deeply aligned with the business they serve.

Start by identifying one Value Object (like a Price or a Name) in your project and making it immutable today!

Leave a comment