一个存储库可以访问另一个存储库通常是否可以接受?特别是在这种情况下,我有一个聚合根,它使用另一个聚合根来确定要添加的实体。它属于Item / Item Type关系的行。项类型是聚合根的原因是它们可以在任何单个项的范围之外的管理工具中单独维护。
如果它确实重要,我只是通过存储库工厂实现创建我的存储库实例,所以我不是通过具体的类名直接创建它。聚合体在任何时候都不知道存储库。
修改 - 更多信息:
具体实现是我们可以将图像附加到文档。我们不仅可以管理文档上的图像,而且还有不同类型的图像(类型被定义为如何实现,例如,与扩展相对)。文档聚合是系统中使用这些图像的少数几种其他对象之一,并且它们并非都使用相同的类型。虽然我们在域服务中附加规则,但更具体地说,这是针对构建文档聚合的。在构建聚合时,我们有五个特定类型的图像,以及另外两个类型的图像。我们单独提取它们是因为它们存储在聚合中的单独列表中。验证不是问题,而是限制在组装文档时评估的图像类型。
答案 0 :(得分:6)
我想这归结为你想要做的事情。如果这是一种验证步骤(例如,删除所有项目类型已过期的项目),您可能会认为它属于服务层或规范。从您使用的语言(即“确定要添加的实体”)来看,它似乎暗示了后者,但如果没有更多细节则很难说。
我想从某种观点来看,没有真正的原因你不能(我绝不是一个超级DDD最纯粹),特别是因为一个Item及其类型可以被视为聚合根,它只是提供防止管理控制台所需的实现细节。
从另一个角度来看,它似乎确实表明你的聚合根之间存在模糊,这可能表明两种不同的背景在起作用。例如,有人可能会说管理工具会为您的主应用程序形成一个单独的有界上下文,因此作为聚合根的Item类型的情况并不真正适用。例如管理工具可能只关注项类型(而不是项目),而主应用程序可能会将项类型视为值对象而不是实体。
<强>更新强>
当你提到组装文档时,这似乎是工厂类的责任,它可以正确地组装一个有效的实体(工厂可以使用图像类型存储库)。存储库应该(在我看来)公开查询和添加操作,而不是配置实体的逻辑(除了可能从持久性中重新水化)。
答案 1 :(得分:0)
使用一个存储库使用另一个存储库不遵循DDD的原则。如果您需要来自一个聚合根的数据以对另一个聚合根执行某些操作,则可以检索第一个根(在应用程序服务层或可能在域服务中),然后将该数据传递到从属聚合根的公共api中,或者在使用单独工厂的聚合根创建的情况下,将其添加到工厂的公共api中。
一个聚合根定义了一个事务边界,其中的数据应保持交易一致性 t。对交易一致性的这种期望不应扩展到该范围之外的任何事物。如果您有一个依赖于另一个存储库的存储库,则您的一个聚合的状态在事务上依赖于另一个聚合的状态,这意味着这些“聚合根”实际上都不是聚合根。
此外,如果您需要更改一个聚合的状态以影响另一聚合的状态,则应为此使用域事件,这会在根之间强制实现最终一致性。