我可以在DDD中使用"不完整"的聚合吗?
时间:2020-03-05 18:42:35 来源:igfitidea点击:
DDD指出,我们只能通过实体的聚合根访问实体。举例来说,假设我们有一个聚合根X,该根X可能有很多子Y实体。现在,对于某些情况,我们一次只真正关心这些Y实体的子集(也许我们正在将它们显示在页面列表中或者其他内容中)。
然后可以实现存储库,这样在这种情况下它返回不完整的聚合吗? IE。一个Xs对象,其Ys集合仅包含我们感兴趣的Y实例,而并非全部?例如,这可能会导致X上执行某些涉及Y的计算的方法的行为不符合预期。
这是否表明有问题的Y实体应被视为提升为总根?
我当前的想法(在C#中)是利用LINQ的延迟执行,以便我的X对象具有一个IQueryable来表示其与Y的关系。这样,我就可以进行透明的延迟加载并进行过滤了……但是让它起作用使用ORM(在我的情况下为Linq to Sql)可能有点棘手。
还有其他聪明的主意吗?
解决方案
回答
我们实际上是在问两个重叠的问题。
- 问题的标题和前半部分是哲学/理论上的。我认为仅通过实体的"聚合根"访问实体的原因是抽象化了我们所描述的实现细节。通过聚合根进行访问是一种通过拥有受信任的访问点来降低复杂性的方法。我们通过遵守约定来消除摩擦/歧义/不确定性。它在根中的实现方式无关紧要,我们只知道当我们请求一个实体时,它就会存在。我不认为这种观点会排除我们所描述的"过滤存储库"。但是要为开发人员提供成功的机会,应该在没有明确说明其"过滤性"的情况下实例化存储库。同样,如果可以对存储库实例进行共享访问,则在调用方进行编码时应明确"过滤"。
- 问题的后半部分是关于在特定平台上的实现。不知道为什么要提到延迟执行,我认为这确实与过滤问题正交。过滤本身可能很难用LINQ来实现。也许不是内联lambda,而是设置它们的集合,然后根据需要的过滤器选择一个。
回答
我认为具有许多子实体的聚合根是代码气味,或者,如果可以的话,则是DDD气味。 :-)通常,我看两个选项。
- 将聚合拆分为许多较小的聚合。这意味着我的原始设计不是最佳的,我需要确定一些新实体。
- 将域划分为多个有界上下文。这意味着,存在特定的场景组使用聚合中实体的公共子集,而其他场景组则使用不同的子集。
回答
吉米·尼尔森(Jimmy Nilsson)在他的书中暗示,我们可以阅读其中一部分的快照,而不必阅读完整的汇总。但是,我们不应将快照类中的更改保存到数据库。
吉米·尼尔森(Jimmy Nilsson)的书第6章:为基础结构查询做准备。 226.
快照模式
回答
允许这样做,因为代码仍然可以编译,但是如果要使用纯DDD设计,则不应有不完整的对象实例。
如果我们害怕加载一个庞大的对象,而我们只会使用其子实体的一小部分,则应该研究LazyLoading。
LazyLoading将延迟我们决定延迟加载的所有内容的加载,直到访问它们为止。一旦代码调用它们,它们便使用回调来调用加载方法。