惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
IT之家
IT之家
博客园 - Franky
Stack Overflow Blog
Stack Overflow Blog
宝玉的分享
宝玉的分享
Recent Announcements
Recent Announcements
Engineering at Meta
Engineering at Meta
S
SegmentFault 最新的问题
V
Visual Studio Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Last Week in AI
Last Week in AI
H
Help Net Security
V
V2EX
H
Hackread – Cybersecurity News, Data Breaches, AI and More
量子位
博客园 - 叶小钗
J
Java Code Geeks
博客园 - 【当耐特】
月光博客
月光博客
爱范儿
爱范儿
人人都是产品经理
人人都是产品经理
酷 壳 – CoolShell
酷 壳 – CoolShell
小众软件
小众软件

博客园 - lightsong

Vision Transformer + BentoML ML Serving/编排工具 Introducing Gemma 3 270M: The compact model for hyper-efficient AI Utopia -- 企业世界模型 trustgraph semantica semantica vs graphti Industrial-Strength Natural Language Processing seata reference with springboot and other valuable demo outbox pattern with springboot Saga pattern with springboot 基于 Sentence Transformers 的具体应用案例 Vault with Keycloak as workload IAM Ontology Reasoning System ADR Claude Code的hook The AI-Native SDLC playbook Introduction to Dapper Introduction to FluentValidation Introduction to AutoFixture Introduction to FluentAssertions Understanding Return Types: IEnumerable, IReadOnlyCollection, and List Introduction to Refit Introduction to Carter Introduction to Minimal APIs Introduction to MediaTr Building Resilient .NET Applications with Polly Understanding Event-Driven Architecture Understanding CQRS in .NET The Transactional Outbox Pattern
Comprehensive Guide to Domain-Driven Design (DDD)
lightsong · 2026-08-25 · via 博客园 - lightsong

Comprehensive Guide to Domain-Driven Design (DDD)

https://jdaniel1987.github.io/DomainDrivenDesign

这是一篇基于你提供的网页内容整理的博客文章。为了便于读者理解,我重新梳理了结构,并对关键代码和概念进行了重点标注。


🚀 全面指南:领域驱动设计 (DDD) 核心与进阶

作者:Jaime Daniel Delgado Ortega
发布日期:2024年9月23日

领域驱动设计(DDD)是一种以业务领域为核心的软件开发战略方法。它通过将软件模型与业务概念对齐,提供了一套管理复杂性的工具。

本文将深入探讨 DDD 的核心概念与进阶模式,并结合 .NET 代码示例,展示如何在项目中应用这些理念。


🧩 DDD 的核心概念

1. 通用语言 (Ubiquitous Language)

通用语言是开发人员和领域专家(如产品经理)之间共享的词汇表。它确保所有参与者对业务概念的理解保持一致。

  • 示例:在代码和业务沟通中,“客户”指代同一对象,“订单状态”的生命周期(待处理、已发货、已送达)在系统中是统一的。

2. 实体 (Entities)

实体是拥有唯一标识(ID)的对象,其身份在生命周期中保持不变。

public class OrderItem 
{
    public required Guid Id { get; set; } // 唯一标识
    public required string ProductName { get; set; }
    public required decimal Price { get; set; }
    public required int Quantity { get; set; }
}

3. 值对象 (Value Objects)

值对象没有唯一标识,它们通过属性值来定义。如果两个值对象的所有属性都相同,则视为相等。值对象通常是不可变的。

代码示例Price 作为一个值对象,通过 record 实现不可变性,并重载了运算符。

public record Price 
{
    public decimal Value { get; init; }

    private Price(decimal value)
    {
        if (value < 0) throw new ArgumentException("Price cannot be negative");
        Value = value;
    }

    public static Price Create(decimal value) => new(value);

    // 重载运算符,支持价格直接相加
    public static Price operator +(Price a, Price b) => new Price(a.Value + b.Value);
}

4. 聚合 (Aggregates)

聚合是一组相关对象的集合,作为一个整体被对待。聚合根(Aggregate Root)负责维护聚合内部的一致性。

public class Order 
{
    public required Guid Id { get; set; }
    public required DateTime OrderDate { get; set; }
    public required Customer Customer { get; set; }
    public required List<OrderItem> Items { get; set; }
}

5. 仓储 (Repositories)

仓储充当聚合根集合的抽象,隔离了领域模型与底层数据访问逻辑。

public interface IOrderRepository 
{
    Task<Order> GetById(int id);
    Task Save(Order order);
}

6. 领域服务 (Domain Services)

当某些领域逻辑不适合放在实体或值对象中时(例如涉及多个聚合的操作),我们将其封装在领域服务中。

public class PaymentService 
{
    public bool ProcessPayment(Order order, PaymentDetails paymentDetails)
    {
        // 处理支付的核心领域逻辑
    }
}

🚀 进阶 DDD 概念

1. 限界上下文 (Bounded Contexts)

限界上下文定义了特定领域模型的边界。同一个概念(如“订单”)在不同的上下文中可能有不同的定义和属性。

  • 销售上下文 (Sales Context):订单包含客户和支付信息。
  • 发货上下文 (Shipping Context):订单仅包含发货地址和追踪号。

2. 领域事件 (Domain Events)

领域事件用于通知系统业务逻辑中发生了重要变化,常用于解耦。

// 定义事件
public record OrderPlacedEvent(int OrderId, DateTime PlacedOn) : IDomainEvent;

// 处理事件
public class OrderPlacedHandler : IEventHandler<OrderPlacedEvent> 
{
    public Task Handle(OrderPlacedEvent domainEvent)
    {
        // 处理订单创建后的逻辑,如发送通知
    }
}

3. 工厂 (Factories)

工厂用于封装复杂聚合的创建逻辑,确保聚合在创建时即满足所有业务规则。

public class OrderFactory 
{
    public static Order CreateOrder(Customer customer, List<OrderItem> items)
    {
        var order = new Order() { CustomerId = customer.Id, /*...*/ };
        foreach (var item in items) order.AddItem(item);
        return order;
    }
}

4. 事件溯源 (Event Sourcing)

事件溯源不直接存储对象的当前状态,而是存储导致状态变化的一系列事件。通过重放事件来重建对象状态。

public class Order 
{
    public OrderStatus Status { get; set; }
    private List<IDomainEvent> _events = new List<IDomainEvent>();

    public void Apply(OrderPlacedEvent @event)
    {
        this.Status = OrderStatus.Placed; // 根据事件更新状态
        _events.Add(@event); // 记录事件
    }
}

5. 防腐层 (Anti-Corruption Layer, ACL)

ACL 用于保护当前领域的模型不受外部系统模型的影响,通过转换层将外部模型翻译为内部领域模型。

public class ExternalCustomerAdapter 
{
    public Customer Convert(ExternalCustomer externalCustomer)
    {
        // 将外部客户模型转换为内部领域客户模型
    }
}

6. 规约 (Specifications)

规约模式将业务规则封装为可重用的对象,用于验证对象或过滤集合。

public class EligibleForDiscountSpecification : ISpecification<Order> 
{
    public bool IsSatisfiedBy(Order order)
    {
        return order.TotalAmount > 100; // 满100元符合折扣条件
    }
}

7. 策略 (Policies)

策略封装了可能影响系统不同部分的复杂业务规则,通常响应领域事件执行。

public class DiscountPolicy 
{
    public decimal ApplyDiscount(Order order)
    {
        if (order.TotalAmount > 500) return order.TotalAmount * 0.10m; // 满500打9折
        return 0;
    }
}

⚖️ DDD 的利与弊

✅ 优势

  • 清晰性:软件设计与业务高度对齐,直观易懂。
  • 可扩展性:通过限界上下文、CQRS 和事件溯源,系统能更好地应对复杂度和性能扩展。
  • 灵活性:更容易适应业务领域的变更。

⚠️ 挑战

  • 学习曲线:概念较多,团队上手难度大。
  • 复杂性:对于简单项目,引入 DDD 可能导致过度设计。

🔗 DDD、整洁架构与 CQRS 的关系

这三者是互补的架构方法:

  1. DDD:专注于业务建模,确保核心逻辑反映真实业务。
  2. 整洁架构:强调关注点分离,将业务逻辑置于中心,独立于框架和数据库。
  3. CQRS:分离读写操作,配合 DDD 的限界上下文,使复杂业务操作的设计更加聚焦。

总结:DDD 提供了一套系统化的方法来管理软件复杂性。虽然它引入了额外的复杂性,但对于大型、复杂的业务系统,其带来的长期可维护性和业务对齐价值是巨大的。


本文基于 Eric Evans 的经典著作《领域驱动设计:软件核心复杂性应对之道》整理。

出处:http://www.cnblogs.com/lightsong/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。