【问题标题】:Manage aggregate boundaries (DDD)管理聚合边界 (DDD)
【发布时间】:2021-05-29 14:13:55
【问题描述】:

我在理解如何在 DDD 中分离聚合时遇到问题。至少,我有一个我不知道如何解决的利益冲突。据我了解,在 DDD 中,聚合被定义为强制执行不变量/一致性的事务边界。但是,这会导致我的聚合变得庞大且难以维护。

我的用例是一个处理电子商务订单的系统。基于业务需求的基本流程如下:

  1. 外部系统(购物车)创建一个Order,其中包含送货地址、帐单邮寄地址和订单项。
  2. 订单通过创建FulfillmentOrder 来履行,该FulfillmentOrder 被发送到外部履行服务提供商。
  3. 外部履行服务发送货物并为给定的履行订单创建一个或多个Shipments。每批货物包括已发货的订单项、出发国家/地区(此外部服务的仓库所在国家/地区)和目的地国家/地区(=== 送货地址国家/地区)
  4. 为每个shipment 创建一个Invoice,增值税/销售税根据Shipment 的出发地和目的地国家/地区计算。

这是域的简化版本。如您所见,有一系列定义明确的步骤,但也有一些纠缠不清……步骤取决于来自先前步骤和不同实体的数据。最重要的是:OrderShipment(因此 OrderInvoice)之间的关系是 1:many 而不是 1:1。

根据上面的聚合定义,我会将所描述的用例设计为一个有界上下文(订单处理),Order 是我的聚合根,Fulfillment OrderShipments 和 Invoices 是实体的集合由聚合根管理。

有几个不变量,跨越所有多个实体,例如:

  • 所有发票的总和不得超过订单总额。
  • 您不能创建包含非现有订单项目的发票。
  • 货件数量不得超过触发货件的履行订单的数量。

将订单作为唯一的聚合根允许强制执行这些不变量。但这会导致订单聚合庞大且难以维护。

另一方面,我可以将 Order、Fulfillment Order、Shipment 和 Invoice 分别建模为聚合。这将使每个聚合体更苗条、更集中。但是我失去了执行上述不变量的能力(这显然对业务不利,但也违反了 DDD 原则)

在领域建模中是否有任何指导方向或策略的优缺点比较?

【问题讨论】:

    标签: domain-driven-design


    【解决方案1】:

    在领域建模中是否有任何指导方向或一些策略的优缺点比较?

    一个好的起点是Memories, Guesses, and Apologies (Helland - 2007)

    聚合边界受领域动态驱动:哪些信息必须一起改变。 “必须一起改变”有一个时间方面 - 我们不是在谈论当系统达到平衡时必须保持一致的信息,而是在事情发生变化时必须保持哪些数据关系。

    要区分这两者,您必须非常注意以下问题:如果报告中的信息过时,企业的成本是多少?

    您不能创建包含非现有订单项目的发票。

    为什么不呢?发生这种情况时,企业的成本是多少?

    时间上的微秒差异不应影响核心业务行为。 -- Udi Dahan, 2010

    您在建模时必须小心假设信息会立即通过您的系统。尤其是在涉及现实世界的系统中,信息以有限的速度传播,并且业务流程包括补偿协议。

    【讨论】:

    • 谢谢。我感觉我对聚合的理解是有缺陷的:我认为不变量的强制执行(在任何时候,无论如何)是主要特征。您将重点放在时间方面(在运输过程中强制执行不变量),而通过其他方式(业务流程)强制执行装运、发票等之间的最终一致性。在我上面的示例中,您确实可以将 Order、Fulfillment Order、Shipment 和 Invoice 建模为单独的聚合体,如果存在用于检查最终不一致并分别补偿此类不一致的业务流程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-22
    • 2020-08-15
    • 2011-05-15
    • 2014-04-26
    • 1970-01-01
    相关资源
    最近更新 更多