Domain driven design 领域驱动设计:不同聚合实体之间的参考

Domain driven design 领域驱动设计:不同聚合实体之间的参考,domain-driven-design,dddd,Domain Driven Design,Dddd,我正在尝试使用领域驱动的设计规则和模式开发我的第一个应用程序。 在我的业务场景中,我必须管理客户列表并跟踪发送到特定客户目的地的所有包。 因此,按照规则,结果是: 客户是一个实体,也是一个聚合对象 目的地是一个实体,它是客户的子实体(因为没有客户它就没有意义) 包是一个实体。它也是另一个聚合对象,因为它是一个不同的事务边界 我使用AddDestination(string destinationName…)方法开发了Customer聚合,该方法负责为客户创建新的目的地 现在我需要开发Pack

我正在尝试使用领域驱动的设计规则和模式开发我的第一个应用程序。 在我的业务场景中,我必须管理客户列表并跟踪发送到特定客户目的地的所有包。 因此,按照规则,结果是:

  • 客户是一个实体,也是一个聚合对象
  • 目的地是一个实体,它是客户的子实体(因为没有客户它就没有意义)
  • 包是一个实体。它也是另一个聚合对象,因为它是一个不同的事务边界 我使用AddDestination(string destinationName…)方法开发了Customer聚合,该方法负责为客户创建新的目的地
现在我需要开发Package类,在这里我必须保存一个对包被运送到的目的地的引用。按照DDD规则,我不能直接引用子实体id,因为我不能引用另一个聚合的子实体。 我该怎么办

  • 我是否必须使用目标所需的数据创建一个新的ValueObejct并将其公开?(通过这种方式,我能够保留目的地的加入和规则,只有通过Customer AggregateRoot才能以书面形式访问)。通过这种方式,外部类可以访问目标的字段,并使用这些字段执行逻辑/检查,但不能改变目标的状态
  • 我是否必须添加DestinationNumber字段(在customer中累进),创建一个包含CustomerId和DestinationNumber的ValueObject,并在包聚合中使用它
  • ?

  • 有人能帮我吗?请详细说明答复,因为我想了解更多此类案例。DDD中的许多聚合更多地是关于事务边界的,而不是表示一个实体的存在是否有意义


    假设A-目的地应该是一个集合

    如果在您的领域中,在自己的交易中修改目的地而不必考虑客户是有意义的,那么可能是您自己错过了目的地

    如果目的地在客户之间共享,或者从一个客户移动到另一个客户(当然是通过身份引用),这也是有意义的


    假设B-目的地肯定是客户的子实体

    另一方面,如果只有customer aggregate可以确保始终满足客户目的地的业务不变量,则只能在客户的交易边界内更改目的地,从而保持客户的子实体

    在您的包中聚合中,您当然只能记住目的地id,例如,如果您只是出于阅读目的才需要它

    但我认为这不是一个好主意。另一方面,不包括客户id也包括在参考中会使这种关系不那么明确。另一方面,如果目的地真的是一个实体(而不仅仅是一个值对象),那么目的地的id只需要在相应客户边界内的域中是唯一的

    因此,如果目的地真的是客户的子实体,我将采用您的选项2,引入一个参考值对象,例如CustomerDestination,包括客户id和任何适合在特定客户范围内识别目的地的标识符


    注意:这对您的数据库模型没有影响,根据您的设计方式,您可能仍然需要在数据库中使用一些全局唯一的代理Id。

    如果我理解正确,我会假设此包必须在某处交付到目的地

    我还假设Customer确实是一个实体,也是一个聚合根,因为它会有诸如更改名称等行为。Package也是一个实体,也是其自身的聚合根,因为它与Customer有不同的交易边界,也有一些行为(比如addDestination)

    在这里,我不认为Destination应该是一个实体,因为它本身没有任何行为或身份,它只是包含一个事实,即这个Destination指的是一个客户。因此,我将把Destination建模为一个值对象,并带有Customer属性Id(可以这样做,因为Customer是聚合根)

    Package的addDestination参数将是Destination的值对象。如果Package必须更改目的地,它可以创建另一个Destination实例并丢弃旧实例


    此外,如果目的地客户的子公司,这是没有意义的,因为可能有一些客户尚未交付任何东西。相反,我会将目的地建模为包的子公司,因为包的每一次创建都是有意义的trong>,它应该有一个目的地(假设任何包裹都必须交付)因此,目的地是在同一个集合中。

    您写道,如果没有客户,目的地就没有意义,后来听起来好像您只想指向目的地。哪一个是真的?根据答案,我建议将所有目的地数据复制为值对象进入包装(如果客户不同意,选项1)