教程 ddd tutorial

聚合与聚合根(Aggregate & Aggregate Root)

在领域驱动设计(DDD)中,聚合(Aggregate) 和 聚合根(Aggregate Root) 是帮助我们划定业务边界、保证数据一致性的关键概念。通过正确设计聚合和聚合根,可以更好地组织系统的复杂业务逻辑。

聚合(Aggregate)

定义

聚合是由多个领域对象组成的集合,这些对象之间具有一定的关系,并且共同协作以保证一致性。聚合中的所有对象通过聚合根进行访问和操作,外部只能通过聚合根与聚合内部的实体进行交互。

特征

  • 内部一致性:聚合内部的对象协同工作,保持业务规则的一致性。
  • 边界:聚合定义了业务领域的边界,保证聚合内部的数据一致性。
  • 聚合根:聚合根是聚合的唯一入口,所有操作都必须通过聚合根来进行。

示例

假设在电商系统中,我们有一个订单聚合。订单聚合包含了订单条目、支付信息、发货信息等对象,但所有操作(如创建订单、修改订单条目)都应该通过订单聚合根进行。

聚合根(Aggregate Root)

定义

聚合根是聚合中的唯一入口点,它负责维护聚合内部的业务规则,并且保证聚合内部对象的一致性。聚合根通常是唯一标识该聚合的实体,外部系统只能通过聚合根来操作聚合中的对象。

特征

  • 唯一入口点:所有操作都必须通过聚合根进行,外部不能直接访问聚合内部的实体。
  • 控制一致性:聚合根确保聚合内部数据的一致性,负责处理所有的业务逻辑。
  • 持久化与加载:聚合根通常负责持久化和加载整个聚合,以保证数据的完整性。

示例

java
public class Order {
    private final String orderId;
    private List<OrderItem> items;
    private Payment payment;
    private Shipping shipping;

    public Order(String orderId) {
        this.orderId = orderId;
        this.items = new ArrayList<>();
    }

    public String getOrderId() {
        return orderId;
    }

    public void addItem(OrderItem item) {
        items.add(item);
    }

    public void setPayment(Payment payment) {
        this.payment = payment;
    }

    public void setShipping(Shipping shipping) {
        this.shipping = shipping;
    }

    public void checkout() {
        // Ensure business rules and consistency are met
    }
}

在上面的示例中,Order 类是聚合根,负责管理订单中的所有对象(OrderItem、Payment、Shipping),并确保它们的一致性和业务规则。

聚合与聚合根的区别

特性 聚合(Aggregate) 聚合根(Aggregate Root)
角色 包含多个领域对象,负责确保一致性 聚合的唯一入口点,负责协调内部对象
一致性 保证聚合内的对象数据一致性 保证聚合根的完整性与一致性
访问方式 只能通过聚合根来访问聚合内部的对象 聚合根是唯一可以被外部访问的对象
业务规则 聚合内的业务规则通过聚合根实现 聚合根负责聚合内所有业务规则的实现

聚合与聚合根的设计原则

  1. 聚合的大小:一个聚合不应过大,避免在业务操作中导致性能问题。聚合的大小应根据领域需求来划定。
  2. 聚合根的职责:聚合根不仅负责数据一致性,还需要处理与外部系统的交互,如持久化和事件发布。
  3. 聚合之间的关系:不同聚合之间应该保持低耦合,避免直接引用其他聚合的实体。如果需要跨聚合操作,可以通过领域服务或领域事件来完成。

实践建议

  • 在设计领域模型时,如果有多个对象需要协作并保持一致性时,可以考虑将它们设计为一个聚合。
  • 确保聚合的边界清晰,聚合内的所有操作必须通过聚合根进行,以确保数据一致性。
  • 通过合理划分聚合和聚合根,避免系统的复杂度过高,并确保业务逻辑能够随着需求变化而演进。

通过合理使用聚合与聚合根,可以帮助开发人员设计出更加清晰和高效的领域模型,支持系统的长期可维护性。