【问题标题】:DDD Repository Awareness of Other Repositories其他存储库的 DDD 存储库意识
【发布时间】:2010-11-23 03:10:12
【问题描述】:

通常可以接受一个存储库可以访问另一个存储库吗?特别是在这种情况下,我有一个聚合根,它使用另一个聚合根来确定要添加的实体。它符合项目/项目类型关系。项目类型是聚合根的原因是它们可以在任何单个项目范围之外的管理工具中单独维护。

如果它确实重要,我只是通过存储库工厂实现创建我的存储库实例,所以我不会直接通过具体的类名创建它。聚合体在任何时候都不知道存储库。

编辑 - 更多信息:

具体实现是我们可以将图片附加到文档中。我们不仅可以管理文档上的图像,而且还有不同类型的图像(例如,类型被定义为如何实现,而不是扩展)。文档集合是系统中使用这些图像的少数几种其他对象之一,它们并不都使用相同的类型。虽然我们确实在域服务中附加了规则,但这更具体地适用于构建文档聚合。在构建聚合时,我们有五个特定类型的图像,以及其他两种类型中的一个。我们单独提取这些,因为它们存储在聚合中的单独列表中。验证不是问题,而是在组装文档时限制正在评估的图像类型。

【问题讨论】:

标签: language-agnostic architecture domain-driven-design ddd-repositories


【解决方案1】:

一个仓库使用另一个仓库不符合 DDD 的原则。如果您需要来自一个聚合根的数据来对另一个聚合根执行某些操作,您可以检索第一个根(在应用程序服务层或可能在域服务中),然后将该数据传递到相关聚合根的公共 api ,或者在使用单独工厂的聚合根创建的情况下,进入工厂的公共 api。

聚合根定义了一个事务边界,其中的数据应该保持事务一致t。这种对事务一致性的期望不应扩展到该边界之外的任何事物。如果您有一个依赖于另一个存储库的存储库,那么您的一个聚合的状态在事务上依赖于另一个聚合的状态,这意味着这些“聚合根”实际上都不是聚合根。

此外,如果您需要更改一个聚合的状态以影响另一个聚合的状态,您应该为此使用域事件,这会在根之间强制最终一致性。

【讨论】:

    【解决方案2】:

    我想这归结为您尝试做的事情。如果这是一种验证步骤(例如,删除所有项目类型已过期的项目),您可能会认为它属于服务层或规范。从您使用的语言(即“确定要添加的实体”)来看,似乎建议使用后者,但如果没有更多细节就很难说。

    我想从某种角度来看,没有真正的理由你不能(我绝不是最纯粹的超级 DDD),特别是因为一个项目及其类型可以被视为一个聚合根,它只是您需要提供可防止的管理控制台的实施细节。

    从另一个角度来看,它似乎确实表明您的聚合根之间存在模糊,这可能表明两种不同的上下文在起作用。例如,有人可能会争辩说,管理工具为您的主应用程序形成了一个单独的有界上下文,因此 Item 类型是聚合根的情况并不真正适用。例如管理工具可能只关心项目类型(而不是项目),而您的主应用程序可能将项目类型更多地视为值对象而不是实体。

    更新

    正如您提到的组装文档,这似乎是可以正确组装有效实体的工厂类的责任(工厂可以使用图像类型存储库)。存储库应该(在我看来)公开查询和添加操作,而不是配置实体的逻辑(除了可能从持久性中恢复)。

    【讨论】:

    • 添加了附加信息。它与验证无关,但与组装有关。我们正在尝试将某些类型的图像“存储”到聚合中的不同实体组中。例如,对于附加信息,可能有五个“示例图像”和一个“摘要图像”。它们都是“图像”,但因“图像类型”而异。组装文档时使用“图像类型”以确保从底层数据源收集正确的图像。
    • 好吧,如果涉及到骨料的组装方式,我会说责任应该落在工厂吗?工厂将了解如何存储图像类型以及如何存储图像。然后,您将通过存储库持久化聚合
    • 是的,我认为这是最好的方法。感谢您的帮助。
    • 您提到的工厂也可以描述为服务吗?我倾向于发现自己总是试图将域对象放入我在 DDD 中阅读过的类别中,因此工厂这个词在模式方面是有意义的,但该工厂通常会被称为 DDD 目的的服务吗?
    猜你喜欢
    • 1970-01-01
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-05
    • 2010-11-11
    相关资源
    最近更新 更多