如何识别聚合根和关联的存储库

How can an aggregate root and associated repositories be identified

场景

我在寻找可能的聚合根和确定正确的问题时遇到了问题 我的应用程序中的存储库。

场景是这样的:我正在写一个库应用来练习DDD。该应用程序允许用户显示所有书籍、创建新书或编辑现有书籍。一本书只有一个作者和一个出版商。在应用程序中用户还可以独立显示、创建和编辑authors/publishers。

实施

目前我正在使用三个不同的存储库 - BookRepository、AuthorRepository 和 PublisherRepository - 以加载书籍、相关作者和出版商。我的 ApplicationService 中使用了所有三个存储库来创建一本新书。

我不明白的地方

看着这段代码,我觉得好像缺少聚合根。我认为 Book class 可能是聚合根。这意味着 BookRepository 将加载所有合并的数据(书籍、作者、出版商),这听起来不错。这在加载单本书时效果很好,但如果我需要显示所有作者并允许用户创建、编辑或删除作者,会发生什么情况?我不能用书 class 作为聚合根来做到这一点。

问题

如何识别聚合根及其关联的存储库?

如果 BookRepository 确实是聚合根...

  1. ...从属实体(即作者和出版商)的方法会是什么样子(例如 repository.GetBookAuthor、repository.UpdateBookAuthor)?

  2. ...如何管理作者/出版商(例如显示所有作者以供编辑)?

在对聚合根建模时,您必须问自己 "What is this entity defined by?",而不是 "What is this entity associated with?" 自然倾向是像数据库一样查看实体 table,然后尝试找到外键。使用 DDD,您正在为业务不变量建模,因此您的实体模型需要反映您试图强制执行的不变量,仅此而已。您将存储库与 DDD 一起使用的原因是您的实体模型可能看起来与您的数据模型不同。如果你所做的只是 CRUD,那么你的模型可能看起来是一样的。在这种情况下,您可能想要重新评估您是否会从 DDD 中获益。

在您的情况下,我会将书籍、作者和出版商建模为它们自己的集合。他们只会通过 ID 关联。因此图书对象将只有一个名为 AuthorID 的 属性。出版商不会有图书对象列表,而只是在图书对象上放置一个 publisherID。原因是出版商不是由他们出版的书来定义的,因为他们可能根本没有书。

由于您主要将制作 CRUD 应用程序作为一种学习体验,因此可能很难真正探索 DDD 的好处。我建议你发明一些业务不变量来尝试和实践模型。

如果您想知道如果您的聚合不具备满足某些查询的所有属性,您的查询需求将如何得到满足,我还建议您阅读 CQRS。