DDD笔记
此篇内容为个人DDD笔记
1 DDD的核心思想
让软件的结构和领域模型对齐,使业务逻辑成为系统的核心
DDD强调:
- 深入业务领域
- 与领域专家协作
- 建立反映业务本质的领域模型
2 DDD分层架构
DDD通常使用四层架构:
┌──────────────────────────────┐
│ API / UI 层(接口层) │ -> 提供外部接口,如 Web API、前端调用
├──────────────────────────────┤
│ 应用层(Application Layer)│ -> 调用领域服务、协调流程、授权、事务管理
├──────────────────────────────┤
│ 领域层(Domain Layer) │ -> 系统核心业务模型(实体、聚合、服务、规则等)
├──────────────────────────────┤
│ 基础设施层(Infrastructure)│ -> 技术细节实现,如数据库、消息队列、第三方接口
└──────────────────────────────┘
3 DDD术语详解
- 实体(Entity)
- 有唯一标识(Id)
- 生命周期长,状态可变
示例:订单、用户、商品
public class Order
{
public Guid Id { get; set; }
public DateTime CreatedAt { get; set; }
}
- 值对象(Value Object)
- 无标识(Id),只有值
- 通常不可变(推荐使用record)
- 相等性基于值比较
示例:地址(国家、城市、街道)、金额(币种 + 数值)
public record Address(string Country, string City, string Street);
- 聚合根(Aggregate Root)
实体和子实体组成聚合(Aggregate),聚合根(AR)是聚合的代表
聚合:业务中相关实体和值对象的集合
聚合根:聚合的入口点,对外只暴露聚合根操作
- 通过聚合根来操作整个聚合(Order控制OrderItem)
- 聚合外部只能引用聚合根,不引用其子实体
示例:Order是聚合根,OrderItem是其子实体
public class Order // 聚合根
{
public Guid Id { get; private set; }
public List<OrderItem> Items { get; private set; } = new();
public void AddItem(Guid productId, int qty, decimal price)
{
Items.Add(new OrderItems(productId, qty, price));
}
}
- 仓储(Repository)
- 提供对象的持久化接口
- 针对聚合根进行操作(保存、查找)
public interface IOrderRepository
{
Task<Order?> GetByIdAsync(Guid id);
Task AddAsync(Order order);
}
- 领域服务(Domain Service)
当业务行为不属于单个实体(如跨多个聚合),放到领域服务
- 业务逻辑不适合放在实体中的“行为”
- 无状态的业务逻辑操作类
public class OrderPricingService
{
public decimal CalculateTotal(Order order)
{
//....
}
}
- 应用服务(Application Service)
制作“业务用例协调”:调用领域层、聚合、仓储、服务等
- 编排用户请求,调用领域对象/服务,完成业务用例
- 不包含业务规则本身
// CQRS风格示例:
// 命令:
public record CreateOrderCommand(Guid CustomerId, List<CreateOrderItemDto> Items);
// 处理器:
public class CreateOrderCommandHandler : IRequestHandler<CreateOrderCommand,Guid>
{
private readonly IOrderRepository _repo;
public async Task<Guid> Handle(CreateOrderCommand request, CancellationToken cancellationToken = default)
{
var order = new Order(request.CustomerId);
foreacch(var item in request.Items)
{
order.AddItem(item.ProductId, item.Quantity, item.Price);
}
await _repo.AddAsync(order);
return order.Id;
}
}
- 领域事件(Domain Event)
聚合内部某些行为完成后,发布领域事件->触发其他动作(通知、发货、积分等)
- 聚合内部业务发生变化后的“事件通知”
- 用于解耦逻辑,支持异步处理
// 定义事件:
public record OrderCreatedEvent(Guid OrderId, DateTime CreatedAt);
// 聚合中发布事件(通常结合Mediator):
public class Order
{
public List<INotification> Events = new();
public void Confirm()
{
Events.Add(new OrderCreatedEvent(Id, CreatedAt));
}
}
// 处理器:
public class OrderCreatedEventHandler : INotificationHandler<OrderCreatedEvent>
{
public Task Handle(OrderCreatedEvent notification, CancellationToken ct = default)
{
// ...
return Task.CompletedTask;
}
}
- 限界上下文(Bounded Context)
- 大型系统的分割单位
- 每个上下文都是独立模型、团队、数据库、接口
示例:订单上下文、用户上下文、库存上下文
通常结合微服务设计,一个限界上下文即一个微服务
上下文之前通信方式:
- API网关
- 消息总线(Kafka,RabbitMQ)
- 远程调用(gRPC)
- 防腐层(Anti-Corruption Layer, ACL)
- 在保护领域模型不被其他系统/上下文“污染”
- 适配外部系统数据结构->转为领域模型
4 DDD精神
简单释义 | |
---|---|
领域优先 | 从业务出发构建模型 |
语言统一 | 所有人员使用统一“通用语言(Ubiquitous Language)” |
模型驱动设计 | 软件结构=业务模型 |
限界上下文 | 大系统拆分为多个模型独立的小系统 |
5 DDD构件关系图
[ API / Application Layer ]
↓
┌────────────Application Service────────────┐
↓ ↓
[Command] →→→→[ Domain Service ]←←→→[ Entity / Aggregate Root ] →→→ Events
↓
[ Value Objects ]
↓
[ Repository ]
↓
[ Infrastructure (EF, DB, MQ, etc.) ]