17

DDD 声明您应该只通过它们的聚合根访问实体。例如,假设您有一个聚合根 X,它可能有很多子 Y 实体。现在,在某些情况下,您一次只真正关心这些 Y 实体的一个子集(也许您将它们显示在分页列表或其他内容中)。

那么是否可以实现一个存储库,以便在这种情况下它返回一个不完整的聚合?IE。一个 X 对象,它的 Ys 集合只包含我们感兴趣的 Y 实例,而不是全部?例如,这可能会导致 X 上执行一些涉及 Ys 的计算的方法无法按预期运行。

这是否可能表明所讨论的 Y 实体应被视为提升为聚合根?

我目前的想法(在 C# 中)是利用 LINQ 的延迟执行,以便我的 X 对象有一个 IQueryable 来表示它与 Y 的关系。这样,我可以通过过滤进行透明的延迟加载......但是让它工作使用 ORM(在我的例子中是 Linq to Sql)可能有点棘手。

还有其他聪明的想法吗?

4

5 回答 5

6

我认为具有许多子实体的聚合根是代码异味,或者如果您愿意的话,是 DDD 异味。:-) 通常我看两个选项。

  1. 将您的聚合拆分为许多较小的聚合。这意味着我的原始设计不是最优的,我需要识别一些新实体。
  2. 将您的域拆分为多个有界上下文。这意味着存在使用聚合中实体的公共子集的特定场景集,而存在使用不同子集的其他场景集。
于 2008-09-20T16:44:03.823 回答
4

Jimmy Nilsson 在他的书中暗示,您可以阅读其中一部分的快照,而不是阅读完整的汇总。但是您不应该能够将快照类中的更改保存到数据库中。

Jimmy Nilsson 的书第 6 章:准备基础设施 - 查询。第 226 页。

快照模式

于 2008-10-06T12:05:25.927 回答
1

你真的在问两个重叠的问题。

  1. 您问题的标题和前半部分是哲学/理论的。我认为仅通过其“聚合根”访问实体的原因是抽象出您所描述的各种实现细节。通过聚合根访问是一种通过拥有受信任的访问点来降低复杂性的方法。您正在通过遵守约定来消除摩擦/歧义/不确定性。不管它是如何在根目录中实现的,你只知道当你请求一个实体时它就会在那里。我不认为这种观点排除了您所描述的“过滤存储库”。但要提供一个成功的坑对于开发人员而言,如果不明确说明其“过滤性”,就不可能实例化存储库;同样,如果对存储库实例的共享访问是可能的,那么在调用者中编码时“过滤性”应该是明确的。

  2. 您问题的后半部分是关于在特定平台上的实施。不知道您为什么提到延迟执行,我认为这与过滤问题确实正交。使用 LINQ 实现过滤本身可能有点棘手。也许不是内联 Where lambda,而是设置它们的集合并根据需要的过滤器选择一个。

于 2008-08-24T15:30:26.920 回答
0

You are allowed since the code will compile anyway, but if you're going for a pure DDD design you should not have incomplete instances of objects.

You should look into LazyLoading if you're afraid to load a huge object of which you will only use a small portion of its child entities.

LazyLoading delays the loading of whatever you decide to lazy-load until the moment they are accessed. They make use of callbacks to call the loading method once the code calls for them.

于 2008-12-02T20:23:16.947 回答
0

那么是否可以实现一个存储库,以便在这种情况下它返回一个不完整的聚合?

一点也不。聚合是改变系统状态的跨国界线。永远不要使用聚合来查询数据。将系统拆分为写入端和读取端。(阅读有关 CQR 和 CQRS 的信息)。当我们认为基于“CRUD”时,我们基于某些资源来实现我们的系统。假设您有“约会”聚合。认为“粗鲁”意味着我们应该实现用例 Create、Update、Delete、GetAll 约会。这意味着 Appointment[] 应该为 GetAll 返回。当您认为基于用例(HexagonalArchitecture)时,您的用例将是 ScheduleAppointment、RescheduleAppointment、CancelAppointment。但对于查询方面,它可以是:/myCalendar。我们在 ClientCalendar 对象中返回特定用户的所有约会。为查询端创建单独的 DTO。切勿为此目的使用聚合。

于 2019-02-04T12:09:54.827 回答