【问题标题】:DDD: Referencing non aggregate rootsDDD:引用非聚合根
【发布时间】:2015-09-03 12:50:42
【问题描述】:

我正在尝试使用一些 DDD 概念来改进我的设计。目前我有 4 个简单的 EF 实体,如下图所示:

有多个TaskTemplates,每个都存储多个TasksItemTemplatesTaskItemTemplates 包含各种信息(描述、图像、默认处理时间)。

用户可以基于TaskTemplate 创建新的具体Tasks。在当前实现中,这还将为每个TaskItemTemplate 创建一个TaskItem,但将来可能会选择一些相关的TasksItemTemplates

我想知道如何在 DDD 中为这个需求建模。不允许从TaskItemTaskTemplateItem 的引用,因为TaskTemplateItem 不是聚合根。但是如果没有这个引用,就不可能得到TaskTemplateItem 的属性。 当然,我可以删除引用并将所有属性从TaskTemplateItem 复制到TaskItem,但实际上我喜欢通过更新TaskTemplateItems 来更新TaskItems 的可能性。


更新:Task(Item)Template 更新的预期行为

应该可以编辑TaskTemplateTaskItemTemplate 和例如修复名称或描述中的拼写错误。我希望这些更改会反映在Task/TaskItem 中。 另一方面,如果 DefaultProcessingTime 被修改,这不应该改变 TaskItem 的持久化 DueDate。

在我当前的实现中,无法将TaskItemTemplates 添加/删除到持久的TaskTemplate,但这将是一个很好的改进。我将如何实现这样的事情?在TaskTemplateTaskItemTemplate 之间添加另一个实体TaskTemplateVersion

更新 2:TaskItemTemplateId 为 ValueObject

再次阅读 Vaughn 的幻灯片后,我认为通过简单的修改,我的模型根据 DDD 是正确的:

不幸的是,我真的不明白,为什么这个设计更好(更好吗?)。好的,TaskItemTemplates 不会有不必要的数据库查询。但另一方面,在使用 TaskItem 时,我几乎需要一个 TaskItemTemplate,因此一切都变得更加复杂。我不能再做类似的事情了

public string Description
{
  get { return this.taskItemTemplate.Description; }
}

【问题讨论】:

  • 顺便说一句,不要将 DDD 实体与 EF 实体混淆。
  • 我知道在完美世界中,DDD 和 EF 之间存在差异。但是也有很多人试图将 DDD 概念直接应用于 EF。我将 DevExpress XAF 与直接基于实体生成的视图一起使用。因此,不可能开发出真正的 DDD 解决方案,但我认为仍然可以使用它来改进我的设计。
  • @krombi 你能解释一下当他们的TaskItems 被修改时你对TaskItems 的期望会发生什么吗?
  • 我更新了我的问题

标签: domain-driven-design


【解决方案1】:

根据您在TaskItemTaskItemTemplate 下列出的属性,我想说它们应该是值对象,而不是实体。因此,如果没有理由(根据您问题中的信息没有)使它们成为实体,请将它们更改为不可变的值对象。

使用该解决方案,您只需通过复制 TaskItemTemplate 的数据来创建 TaskItem

关于您描述的更新场景,请参见以下解决方案:

  • TaskItems 是从 TaskItemTemplate 的特定版本创建的。使用TaskItem 记录该版本。
  • TaskTemplate 负责更新其项目并跟踪其版本。
  • 如果模板发生更改,如果需要立即采取行动,请通知从该模板派生的所有Tasks。如果您只是希望能够在以后“拉入”模板更改(而不是在模板更改时采取行动),您只需比较版本。

要做出明智的决定,您必须充分了解不变性的优缺点。只有这样,您才会看到将事物建模为值对象的好处。我认为该主题非常有价值的一个来源是Eric Lippert's series on immutability

此外,Vaughn Vernon 的实施 DDD 一书很好地解释了值对象和实体的概念。

【讨论】:

  • 第一:谢谢!但我真的对 DDD 感到困惑。尽管 ValueObjects/Entities 的概念乍一看似乎很简单,但您可以在 SO 上找到很多不同的意见。 TaskItem:它有一个可变的TaskStatus。因此它是一个实体,不是吗? TaskItemTemplate:是否可以拥有一组 VO?有些人说不。 Copy-On-Create 方法:是的,这应该可行。 TaskItemTemplate 还存储一个 Image 属性。我真的应该多次复制这张图片吗?我真的很喜欢 DDD 的想法,但有时很难离开以数据为中心/DB/CRUD 的方式。
  • 是的,如果你的 TaskItem 需要是可变的,它就不能是一个值对象。但这会使您的设计更加复杂。您可以尝试在任务中而不是在项目中管理 TaskStatus。不过,我不知道这在您的应用程序中是否有意义。为什么不能列出 VO 列表?这是荒谬的。毕竟,您可以创建数字列表:-)。 VO(或者更确切地说是不可变对象)的好处是它们可以共享(因为它们保证不会更改),因此您不需要复制图像。
  • 我不明白如果 TaskItem 是可变的,为什么设计会变得更加复杂。你能详细说明一下吗?我看到的一个问题:无法共享 TaskItem 实体,例如经理不能监视一组特定的任务项,因为它们属于不同的 AR。观看 ValueObject 是可能的。令人困惑...反对 VO 列表的论点:mhinze.com/2009/01/10/… 如果我将 TaskItemTemplate 建模为 VO 并使用您的版本概念,我将如何搜索要更新的 TaskItems?如果没有身份,我必须通过平等搜索?!
  • 很抱歉,您链接的文章绝对是垃圾。不仅在他的例子中展示了作者可变值对象,他也完全没有理解值对象的概念。
  • programmers.stackexchange.com/questions/261444/… Vernon 也使用实体集合而不是 ValueObjects,因为 db 约束。不要误会我的意思:我非常感谢您的帮助,但我仍然感到困惑。阅读博客/书籍/SO 问题时,一切都有意义,但如果我尝试使其适应我的问题,我会有点迷茫。
猜你喜欢
  • 2012-11-04
  • 2016-03-21
  • 1970-01-01
  • 2020-10-24
  • 1970-01-01
  • 2012-02-19
  • 1970-01-01
  • 2010-12-01
  • 1970-01-01
相关资源
最近更新 更多