领域驱动设计(Domain-Driven Design, DDD)介绍
是一种专注于业务复杂性的软件开发方法论,通过将代码与业务领域深度绑定,解决复杂业务问题。以下是对 DDD 的核心概念和分层架构的详细介绍:
1. DDD 的核心目标
- 将业务逻辑作为核心,而非技术实现。
- 统一业务专家与开发人员的语言(Ubiquitous Language,通用语言)。
- 通过领域模型(Domain Model) 直接映射业务规则。
2. DDD 的两大设计维度
战略设计(Strategic Design)
- 划分业务边界:识别核心领域、支撑子域和通用子域。
- 限界上下文(Bounded Context):
每个上下文代表一个独立的业务模块,拥有自己的领域模型和术语。
示例:电商系统中的订单上下文
、库存上下文
、支付上下文
。
战术设计(Tactical Design)
- 在限界上下文内部,用代码实现领域模型的具体模式,例如:
- 实体(Entity):有唯一标识的对象(如
User
、Order
)。 - 值对象(Value Object):无标识,通过属性定义的对象(如
Money
、Address
)。 - 聚合根(Aggregate Root):管理一组相关对象的入口(如
Order
聚合根包含OrderItem
)。 - 领域服务(Domain Service):处理无状态业务逻辑(如
PaymentService
)。 - 仓储(Repository):封装数据访问逻辑(如
IOrderRepository
)。 - 领域事件(Domain Event):表示业务状态变化的事件(如
OrderPlacedEvent
)。
- 实体(Entity):有唯一标识的对象(如
3. DDD 的分层架构
典型的 DDD 分层架构如下:
领域层(Domain Layer)
- 核心:包含实体、值对象、聚合根、领域服务和领域事件。
- 职责:实现业务规则,与技术无关。
- 目录示例:
YourProject.Domain/ ├── Entities/ // 实体类 ├── ValueObjects/ // 值对象 ├── Aggregates/ // 聚合根 ├── Services/ // 领域服务 ├── Events/ // 领域事件 └── Repositories/ // 仓储接口(不包含实现)
应用层(Application Layer)
- 职责:协调领域层对象,处理用例(如
CreateOrderCommand
)。 - 示例:csharp复制
public class OrderService { private readonly IOrderRepository _repository; public void CreateOrder(CreateOrderDto dto) { var order = new Order(dto.Items); _repository.Add(order); } }
基础设施层(Infrastructure Layer)
- 职责:实现仓储、数据库访问、第三方服务集成。
- 示例:csharp复制
public class OrderRepository : IOrderRepository { public void Add(Order order) { // 调用 EF Core 保存到数据库 } }
用户接口层(Presentation Layer)
- 职责:处理 HTTP 请求、API 接口、UI 交互。
- 示例:csharp复制
[ApiController] public class OrderController : ControllerBase { private readonly OrderService _service; [HttpPost] public IActionResult CreateOrder(CreateOrderDto dto) { _service.CreateOrder(dto); return Ok(); } }
4. DDD 的适用场景
- 业务逻辑复杂:需要深度建模(如金融、电商、医疗系统)。
- 长期演进:需求频繁变化,需保持代码可维护性。
- 多团队协作:通过限界上下文解耦模块。
5. DDD vs. 传统 CRUD 开发
维度 | DDD | CRUD(传统三层架构) |
---|---|---|
核心目标 | 解决业务复杂性 | 快速实现数据增删改查 |
代码结构 | 按业务领域划分 | 按技术层次划分(Controller/Service/DAO) |
灵活性 | 高(适应业务变化) | 低(业务逻辑分散在代码各处) |
适用场景 | 复杂业务系统 | 简单管理后台、工具类应用 |
6. 实施 DDD 的关键步骤
- 与业务专家协作:定义通用语言(Ubiquitous Language)。
- 识别限界上下文:划分业务模块(如订单、库存、物流)。
- 建模领域对象:确定实体、值对象、聚合根。
- 设计分层架构:分离领域层、应用层、基础设施层。
- 迭代验证:通过领域事件和测试驱动开发(TDD)确保模型正确性。
7. 挑战与建议
- 挑战:
- 领域模型需要持续演进。
- 团队需高度理解业务逻辑。
- 建议:
- 从小处开始:先在一个限界上下文中实践。
- 使用工具:如事件风暴(Event Storming)辅助建模。
- 避免过度设计:仅在复杂场景使用 DDD。
代码示例:订单聚合根
csharp复制// 领域层:Order.cs(聚合根)
public class Order : IAggregateRoot
{
public Guid Id { get; private set; }
public List<OrderItem> Items { get; private set; }
public DateTime CreatedAt { get; private set; }
// 业务逻辑:创建订单
public Order(List<OrderItem> items)
{
if (items.Count == 0)
throw new Exception("订单至少需要一个商品");
Id = Guid.NewGuid();
Items = items;
CreatedAt = DateTime.UtcNow;
}
}
// 值对象:OrderItem.cs
public class OrderItem
{
public Guid ProductId { get; }
public int Quantity { get; }
public decimal Price { get; }
public OrderItem(Guid productId, int quantity, decimal price)
{
ProductId = productId;
Quantity = quantity;
Price = price;
}
}
通过 DDD,你可以将复杂的业务逻辑清晰地映射到代码中,使系统更易于维护和扩展。如果需要更具体的落地指导(如如何设计聚合根或处理领域事件)