0

引述来自DDD:解决软件核心的复杂性(第 150 页)

一个)

对 VALUE 的全局搜索访问通常是没有意义的,因为通过其属性查找 VALUE 将等同于创建具有这些属性的新实例。也有例外。例如,当我计划在线旅行时,我有时会保存一些预期的行程并稍后返回以选择一个进行预订。这些行程是价值(如果有两个由相同的航班组成,我不在乎哪个是哪个),但它们已与我的用户名相关联并完整地为我检索。

我不明白作者的推理,为什么让Itinierary值对象全局可访问而不是客户端必须全局搜索Customer root entity然后从它遍历到这个Itinierary对象更合适?

b)

必须通过基于对象属性的搜索来全局访问持久对象的子集……它们通常是实体,有时是具有复杂内部结构的值对象……

为什么具有复杂内部结构的值对象更常见于全局可访问而不是更简单的值对象

c) 无论如何,是否有一些关于如何确定特定值对象是否应该全局可访问的通用指南?

更新:

一个)

没有任何领域的理由可以通过客户实体进行行程遍历。如果任何行为都不需要客户实体,为什么还要加载它?查询通常在不使行为域复杂化的情况下得到最好的处理。

我对此可能错了,但是当用户(即客户根实体)登录时,域模型检索用户的不是很常见Customer Aggregate吗?

如果用户可以选择预订航班,那么他们也会经常检查Itineraries(虽然英语不是我的第一语言,所以这个词Itinerary实际上可能与我认为的意思有点不同)他们已经选择或预订。

既然Customer Aggregate已经从数据库中检索到,为什么在已经与 一起检索时发出另一个全局搜索Itinerary(可能会在 DB 中搜索它)Customer Aggregate

C)

规则很简单 IMO - 如果有需要的话。它不取决于 VO 本身的结构,而是取决于用例是否需要特定 VO 的实例。

但是这个 VO 实例必须与某个实体相关(即Itinerary与特定实体相关Customer),否则正如作者指出的那样,我们可以简单地使用这些属性创建一个新的 VO 实例,而不是通过其属性搜索 VO 吗?

第二次更新:

a)从您的链接

另一种表达关系的方法是使用存储库。

当通过repository表达关系时,您是否实现了一个SalesOrder.LineItems属性(我对此表示怀疑,因为您建议不要直接调用 repositories 的实体),而后者又调用了repository,或者您是否实现了类似的东西SalesOrder.MyLineItems(IOrderRepository repo)?如果是后者,那么我认为不需要SalesOrder.LineItems财产?

b)

要记住的重要一点是聚合并不意味着用于显示数据。

确实,域模型不关心上层将如何处理数据,但如果不在应用程序UI层之间使用 DTO,那么我假设UI将提取数据以从聚合中显示(假设我们将整个发送到 UI聚合而不仅仅是驻留在其中的某个实体)?

谢谢

4

1 回答 1

1

a) 没有域理由使行程可以通过客户实体。如果任何行为都不需要客户实体,为什么还要加载它?查询通常在不使行为域复杂化的情况下得到最好的处理。

b)我假设他的推理是复杂的值对象是您想要查询的对象,因为您无法轻松地重新创建它们。这个问题和所有与查询相关的问题都可以使用read-model 模式来解决。

c) 规则很简单 IMO - 如果有需要的话。它不取决于 VO 本身的结构,而是取决于用例是否需要特定 VO 的实例。

更新

a) 客户集合不太可能引用客户的行程。原因是我看不到行程将如何与客户集合中存在的行为相关联。如果只需要显示一些数据,则根本不需要加载客户聚合。但是,如果您确实加载了聚合并且它确实包含您需要的参考数据,那么您也可以显示它。要记住的重要一点是聚合并不意味着用于显示数据。

c) 客户和行程之间的关系可以用一个共享 ID 来表示——每个行程都有一个 customerId。这将允许根据需要进行查找。但是,仅仅因为这两件事是相关的,并不意味着您需要遍历客户才能到达相关实体或值对象以进行查看。更一般地,关联可以作为直接引用或通过存储库搜索来实现。无论哪种方式都需要权衡取舍。

更新 2

a) 如果使用存储库实现,则没有LineItems属性 - 没有直接引用。相反,要获取行项目列表,需要调用存储库。

b) 或者您可以创建一个类似 DTO 的对象,一个读取模型,它将直接从存储库返回。存储库可以依次执行简单的 SQL 查询来获取所有必需的数据。这使您可以获取不属于聚合但相关的数据。如果聚合确实具有视图所需的所有数据,则使用该聚合。但是,一旦您需要更多与聚合无关的数据,请切换到读取模型。

于 2013-01-22T20:08:59.653 回答