DDD,聚合和实体

时间:2016-06-29 14:36:01

标签: domain-driven-design ddd-repositories

我有以下域对象结构

Invoice
 - List<Items>
      - Service

Invoice有一个项目列表,每个项目都有一个服务。

数据库结构如下

Invoices Table
Items Table (fk to invoice, fk to service)
Services Table

如果我理解正确,Invoice是聚合的,item是实体,service是这个场景中Item的值对象?

如果我需要向数据库添加新服务会发生什么。我应该创建一个新的Service类,然后为该场景聚合,并拥有它自己的存储库吗?

2 个答案:

答案 0 :(得分:4)

Invoice
 - List<Items>
      - Service

首先要注意的是 - 这是对结构的描述。 DDD中聚合的动机不是结构,而是行为。聚合的作用是确保对结构的修改符合业务规则。

  

如果我理解正确,Invoice是聚合的,item是实体,service是这个场景中Item的值对象?

关闭,但术语比那更模糊(抱歉)。如果此结构表示聚合边界内的状态,则Invoice将是充当aggregate root的实体,而聚合本身通常称为Invoice aggregate

项目和服务可能是值类型,也可能是实体。您需要更多信息才能确定。从名称猜测(应该从普遍存在的语言中提取),它们可能都是实体。 ServiceNameServiceId更有可能是价值类型。

重点:如果这些是实体,它们的生命周期从属于Invoice的生命周期。换句话说,发票的“级联删除”将带有项目和服务。

  

如果我需要向数据库添加新服务会发生什么。我应该创建一个新的Service类,然后为该场景聚合,并拥有它自己的存储库吗?

略微向后:持久性组件支持域模型,而不是相反。

如果服务是一个实体,并且该实体的生命周期独立于任何一个发票(例如,如果两个不同的发票可以引用“相同”服务),那么服务实体应该是不同的聚合比发票,发票的状态包含对服务的引用,而不是服务本身。

如果这是正确的模型,那么服务聚合将拥有自己的存储库。

答案 1 :(得分:0)

服务可以自己存在吗? - 看起来他们可以根据你上面的内容。 如果您需要向数据库添加新服务(我假设服务是独立的),那么您需要创建服务聚合根。还有一个服务存储库等用于添加它。 聚合根和存储库始终是一对一的。他们的关键是了解您域中的聚合根源。正确定义后,存储库是自定义的。 请注意,如果您需要在上面的示例中向发票中添加类似新项目的内容,则必须通过Invoice存储库执行此操作。原因很简单,因为Item是一个实体而不是聚合根。