Ayy*_*ppa 3 domain-driven-design aggregate ddd-repositories aggregateroot dddd
在阅读了大量帖子后,我意识到如果一个概念/上下文存在聚合根,我们需要为整个概念/上下文创建一个存储库。
如果是这样,我看到内部实体不会有任何存储库。如果是这样,这些内部实体如何保存到数据库中?
我在聚合根下有许多内部实体。所以,想知道如果我需要在聚合根存储库下保存所有内部实体,它会变得臃肿。请建议在这种情况下可以做什么。
此外,我的内部实体将在持久性级别转到他们自己的每个表。如果我不允许以这种方式存储内部实体,请纠正我。
示例
考虑我有一个 Restaurant 作为聚合根。它可以对名为 Review 的实体进行分组。餐厅存在评论,没有它就无法存在。
在这里,如果 Review 是一个内部实体,并且一个餐厅可以有很多评论,Reviews 将保存在一个单独的表中。但是由于餐厅聚合根只有一个餐厅存储库,因此如何/在何处处理保存评论。
我想补充一下CPerson的答案。
这种不结合上下文的讨论往往毫无意义。每个案例都是针对具体情况的,很少能归结为持久性问题。
在上述情况下,我永远不会将 Review 建模为 Restaurant 聚合中的实体。这不是持久性问题,而是建模问题。
有一些 DDD 书籍,我相信阅读几篇博客文章不足以理解 DDD 的战略和战术模式。这些模式之一确实是聚合模式。简而言之,聚合是一致性边界。聚合总是特定于上下文的(就像其他任何东西一样)。
如果您正在对餐厅管理系统或食品配送系统进行建模,评论可能会处于单独的上下文中。不存在“餐厅上下文”这样的上下文。这就是限界上下文模式的全部要点。在您的示例中,它可能是餐厅评论上下文。评论的发生与食物、营业时间和餐桌预订无关。
如果你正在为 TripAdviser 之类的东西建模,基本上你只有评论。在这种情况下,评论或多或少与正在评论的内容无关。那么,你的模型就完全不同了。
评论的数量不断增长,因此将所有评论作为实体进行聚合并没有多大意义。同样,聚合是一致性边界。您是否会说,如果另一条评论是一星,则不能发布该评论?我不这么认为。关于评论,您试图在餐厅聚合中保护的不变量是什么?您是否需要限制评论数量以根据这些评论更改餐厅的状态?我认为事实并非如此。因此,评论本身可以是一个聚合,因为所有评论都是完全独立的。
评论聚合中的餐厅可以是保存餐厅 ID 的简单值对象。在构造这个值对象时,您需要确保给定的餐厅确实存在并可供评论。当餐厅消失时,您确实需要清除评论。但它也是特定于上下文的。餐厅可能会关门,但您仍然保留评论。
我同意其他答案中提出的一些观点,即您可能不想像那样建模,但我认为您的问题本身尚未得到解答。例如,它非常好。
所以这里是:
您不为实体创建存储库(如在 DDD 存储库中),仅为聚合根创建。因此,在您的示例中,应用程序层可能类似于:
Restaurant restaurant = restaurantRepository.findById(23)
restaurant.addReview(review)
restaurantRepository.save(restaurant)
Run Code Online (Sandbox Code Playgroud)
另请注意,操作是在聚合根上完成的。所以一般来说,应用层中的命令通常是:加载聚合,对其执行操作,保存它
聚合被保存为一个整体,并带有它的实体。存储库后面发生的事情取决于您的基础架构。当然,由于存储库属于域,我们不关心那里的基础设施。
那么基础设施层的实现(这些只是它可能如何实现的一些例子):
如果您有 RDBMS,您确实希望将实体存储在它们自己的表中。在这里你可以使用:
也看看这个问题
此外,在某些情况下,您可能仅出于技术原因拆分聚合。如果您有一个包含大量实体的聚合,并且处理起来很繁重,那么您可能希望纯粹出于技术原因将其拆分为两个聚合。但这是您试图避免的事情,并且仅在真正必要时才这样做。
如果是这样的话,我发现内部实体不会有任何存储库。如果是这样,这些内部实体如何保存到数据库中?
聚合代表一致性边界。如果一个实体由聚合拥有并且需要确保一致性,那么它应该与聚合根一起持久化。
所以,想知道如果我需要将所有内部实体保存在聚合根存储库下,它会变得臃肿。
是的,会的。如果这是一个真正的问题,您可以考虑使用 ORM。ORM 将在内存中维护以聚合根为根的图,并确保根据需要保留更改。
此外,我的内部实体将在持久性级别访问它们自己的每个表。如果我不允许以这种方式存储内部实体,请纠正我。
尝试将您的域与持久性策略分开考虑。您有一个映射到关系模式的域模型。关系模式不应驱动域的设计。