5

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

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

但是当我开始构建我的应用程序时,我最终需要为供应商单独列出、创建和更新表单。这个列表很简单,我可以调用 Company.Suppliers,创建很糟糕,我可以做 Company.Suppliers.Add(supplier),但更新让我头疼。由于我只需要一个实体,而且我不能在表单之间准确地将其粘贴到内存中,因此我最终需要重新获取公司和所有供应商,并找到我需要绑定到它的那个,然后再次对其进行修改并保留它回到数据库。

如果我有供应商的存储库,我真的只需要做一个 GetOne。我可以通过将 GetOneSupplier 添加到我的 Company 或 CompanyRepository 来添加一些解决方法,但这似乎很垃圾。

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

tldr;

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

4

2 回答 2

37

根据您的术语,我假设您正在根据 Eric Evans 的书执行 DDD。听起来您已经在最初的建模过程中发现了一个问题,并且您做对了。

你提到你认为供应商是Value Object......我认为不是。AValue Object是主要由其属性确定的东西。例如,日期“2009 年 9 月 30 日”是一个值对象。为什么?因为具有不同月/日/年组合的所有日期实例都是不同的日期。具有相同月/日/年组合的所有日期实例都被视为相同。我们永远不会争论将我的“2009 年 9 月 30 日”换成你的,因为它们是相同的 :-)

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

因此,在您的示例中,我会考虑一个供应商Entity,因为我假设每个供应商主要由其 ID 而不是其属性来标识。我自己的公司与世界上另外两家公司同名——但我们并非都可以互换。

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

现在,就目前而言Aggregate Root,您希望专注于对象的生命周期和访问控制。考虑到我有一个博客,其中有很多帖子,每个帖子都有很多评论——这些Aggregate Root(s)在哪里?让我们从评论开始。在没有帖子的情况下发表评论有意义吗?你会创建一个评论,然后去找一个帖子并将其附加到它上面吗?如果你删除一个帖子,你会保留它的评论吗?我建议一个帖子是一个Aggregate Root带有“叶子”的帖子 - 评论。现在考虑博客本身——它与帖子的关系类似于帖子和评论之间的关系。在我看来,它也是一个Aggregate Root带有“叶子”的帖子。

所以在你的例子中,公司和供应商之间是否存在牢固的关系,如果你删除一家公司(我知道......你可能只有一个公司实例),你也会删除它的供应商?如果你删除“星巴克”(美国的一家咖啡公司),它所有的咖啡豆供应商都将不复存在吗?这一切都取决于您的域和应用程序,但我建议您很可能都不EntitiesAggregate Roots,或者考虑它们的更好方法是它们是聚合根,每个都没有“叶子”(没有聚合)。换句话说,公司不控制对供应商的访问或控制供应商的生命周期。它只是与供应商建立一对多的关系(或者可能是多对多)。

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

我希望这有帮助。也许埃里克·埃文斯潜伏在这里,会告诉我我在哪里偏离了他的范式。

于 2009-10-01T03:21:01.890 回答
1

对我来说听起来很简单 - 供应商应该有自己的存储库。如果一个实体在模型中独立存在的任何逻辑可能性,那么它应该是一个根实体,否则无论如何你最终都会重构,这是多余的工作。

根实体总是比值对象更灵活,尽管预先进行了额外的实现工作。我发现随着模型的发展,模型中的值对象会随着时间的推移变得越来越少,而保留为值对象的实体通常是您可以从第一天开始就以这种方式进行逻辑约束的实体。

如果公司共享供应商,那么将供应商作为根实体也会消除数据冗余,因为您不会复制每个公司的供应商定义而是共享引用,并且公司和供应商之间的关联也可以是双向的,这可能产生更多的利益。

于 2009-10-01T03:11:52.123 回答