域驱动设计:何时创建聚合根?

Mic*_*ook 5 asp.net-mvc bdd domain-driven-design

我正在尝试使用ASP.NET MVC项目首次实现DDD,而我正在努力解决一些问题.

我有2个相关实体,一个公司和一个供应商.我最初的想法是公司是一个集合根,供应商是公司的价值对象.所以我有一个公司的存储库,没有供应商的存储库.

但是当我开始构建我的应用程序时,我最终需要为供应商单独列出,创建和更新表单.这个名单很容易我可以打电话给Company.Suppliers,而且创建很糟糕我可以做Company.Suppliers.Add(供应商),但更新让我很头疼.由于我只需要一个实体,而且我无法将它完全固定在表单之间的内存中,我最终需要重新获取公司和所有供应商并找到我需要绑定到它的那个并再次修改它并坚持下去回到db.

如果我有供应商的存储库,我真的只需要做一个GetOne.我可以通过向我的公司或CompanyRepository添加GetOneSupplier来添加一些解决方法,但这看起来很垃圾.

所以,我真的想知道它是否真的是一个价值对象,而不是一个完整的域实体本身.

tldr;

是否需要单独的列表/创建/更新视图/页面,表明实体应该是它自己的根?

Sin*_*hot 35

根据您的术语,我假设您正在根据Eric Evans的书执行DDD.听起来你已经发现了最初的建模问题并且你是对的.

你提到你认为供应商是Value Object...我建议不是.A Value Object主要由其属性识别.例如,日期"2009年9月30日"是值对象.为什么?因为具有不同月/日/年组合的所有日期实例都是不同的日期.具有相同月/日/年组合的所有日期实例被视为相同.我们永远不会因为它们是相同的而交换我的"2009年9月30日"因为它们是相同的:-)

一个Entity在另一方面主要由它的"ID"识别.例如,银行帐户有ID - 它们都有帐号.如果银行有两个帐户,每个帐户有500美元,如果他们的帐号不同,那么他们也是.他们的属性(在这个例子中,他们的平衡)不识别它们或暗示平等.我敢打赌,即使他们的余额相同,我们也会争论交换银行账户:-)

因此,在您的示例中,我会考虑供应商Entity,因为我认为每个供应商主要由其ID而不是其属性来识别.我自己的公司与世界上另外两家公司共享其名称 - 但我们并非都可以互换.

我认为你的建议是,如果你需要CRUD一个对象的视图,那么Entity根据经验这可能是正确的,但你应该更多地关注使一个对象与其他对象不同的东西:属性或ID.

现在Aggregate Root,您希望专注于对象的生命周期和访问控制.考虑到我有一个博客,其中有许多帖子,每个帖子都有很多评论 - 这些是Aggregate Root什么?让我们从评论开始.没有帖子发表评论是否有意义?你会创建一个评论,然后找一个帖子并将其附加到它?如果您删除帖子,是否会保留其评论?我建议一个帖子是Aggregate Root一个"叶子" - 评论.现在考虑博客本身 - 它与帖子的关系类似于帖子和评论之间的关系.在我看来,这也是Aggregate Root一个"叶子" - 帖子.

因此,在您的示例中,公司和供应商之间是否存在强大的关系,如果您删除公司(我知道......您可能只有一个公司实例),您还会删除其供应商吗?如果你删除"星巴克"(美国的一家咖啡公司),它的所有咖啡豆供应商都不复存在吗?这一切都取决于你的域和应用程序,但我建议很可能既不是你的更EntitiesARE Aggregate Roots,或者一个更好的方式来思考他们的是,他们均没有"叶子"集合根(无聚集).换句话说,公司无法控制对供应商生命周期的访问或控制.它只与供应商(或许多对多)建立了一对多的关系.

这带给我们的是Repositories.A Repository用于存储和检索Aggregate Roots.你有两个(从技术上讲,它们不会聚合任何东西,但比说"存储库存储聚合根或聚合中没有叶子的实体"更容易),因此你需要两个Repositories.一个用于公司,一个用于供应商.

我希望这有帮助.也许埃里克埃文斯潜伏在这里,并会告诉我我偏离了他的范例.