gpt4 book ai didi

domain-driven-design - 真实世界的 DDD : Structuring the Domain Layer

转载 作者:行者123 更新时间:2023-12-04 02:21:49 25 4
gpt4 key购买 nike

我正在尝试从以数据为中心的设计和开发转变为 DDD,并且已经阅读了 Evans 和 Nillson,但仍然无法解决我应该如何构建域层的问题。我确定我当前项目的性质没有帮助!

一点背景

该应用程序是管理人员评估的内部解决方案。 HR 人员将创建评估"template",其中包含一组问题,团队领导和经理要为他们的每个直接下属完成这些问题。答案将保留以供审核和审查。这些评估可以用于各种各样的事情,例如对公司计划的反馈、绩效评估等。

我以数据为中心的一面

不是为了影响解决方案而是突出我以数据为中心的心态,我已经对数据库模式有了一个愿景,并将其包含在此处仅供引用(因为图片表示一千个字):

enter image description here

正如预期的那样,模式已标准化,并且与我的应用程序中处理数据的方式不匹配。而且,我忽略了查找表等,以尽量减少手头的问题。

用例

第一个用例是检索并显示用户需要完成的评估列表。这将在用户首次登录应用程序时显示,起初看起来相对容易,但有两个问题: 1 - 评估是基于时间的,因此可能需要每月、每年或每“x”一次基于员工周年日期的年数;并且, 2 - 用户可以保存正在进行的评估并稍后完成。因此,该列表应包含到期的评估以及任何正在进行的评估。

接下来,当用户选择要执行的评估时,我需要检索该评估(当前版本)的所有问题,以便将它们显示给用户。在评估过程中的任何时候,用户都可以保存当前的结果。只有在整个评估完成后,它才能真正“提交”——或提交。

第三,HR 需要一种方法来根据主管提供的回复重新生成评估。

最后,HR 能够创建和修改评估——并且它们是版本化的。因此,每当有人修改评估时,就会创建一个新版本,并且该版本成为执行的任何新评估的模板(任何正在进行的评估继续使用其原始模板)。

领域模型

不按顺序工作,对我来说,我将有一个评估实体作为聚合根来满足第四个用例是有意义的。它将有一个 Section 实体的子集合,而 Section 实体又将有一个 Question 实体的子集合。他们都是实体,因为他们有身份(是的?)。评估是消费代码用于持久性、验证等的对象(尽管 Section 和 Question 实体验证自己并将状态汇总到根评估)。我的目标是从消费者那里抽象出版本控制并在数据持久层中实现它(好还是坏主意?)

这意味着我还将拥有一个为我处理持久性的 AssessmentRepository,可能还有一个在需要时创建新评估的 AssessmentFactory。

更大的问题来自其他用例。我是否也有 EmployeeAssessment 聚合根?或者它只是一个实体?

查看用例,我需要通过多种方式使用此信息。首先,当我生成要显示给用户的评估列表时,我不仅要根据评估频率评估直接报告列表,还需要知道我是否已经开始和/或完成了评估对于那个员工。这来自 EmployeeAssessments 表。另一种情况是当用户实际执行评估时,我正在与 EmployeeAssessments 和 Responses 表进行交互。

从 UI 的角度来看,当用户执行评估时,他们对内部数据结构等一无所知。我需要向 UI 提供该评估的问题列表,以显示并接受响应列表以保持不变。这是否会导致带有随附存储库等的第二个根?

第三个用例的相似之处在于 HR 希望能够在以后重新生成带有响应的评估。但是,我认为这里可以使用执行评估时使用的相同过程,因为恢复现有评估将需要相同的数据,唯一的区别是读/写能力与只读的 HR。

早点收起来吧!

好吧,我已经说得够多了,我想我已经清除了我的脑袋。我感谢任何方向、建议、批评等。正如我所说,我正在尝试进行跳跃并认为我理解这些概念,现在是应用它们的问题。谢谢!!!

最佳答案

几年前我和你一样跳了起来。我现在正在从普通的 DDD 跳转到 CQRS(请参阅 cqrsinfo.com/)。

我会以 CQRS 的方式来处理这个问题,即使用事件存储并在架构级别上将读取与写入完全分开。但是,我认为您提到的问题更符合普通的 DDD 方式 - 所以我将在这种情况下回答。

您需要完全摆脱“数据驱动”的想法。从主要工作流程开始。第一次和第三次使用本质上只是获取操作。我将首先关注聚合根状态发生变化的用例。所以用例 2,即“执行评估”将是一个很好的起点。

  • 正如您正确指出的那样,聚合根将是评估。可以创建“PerformAssessmentService”类(相当于域服务),并且您的执行评估工作流将存在于此处。此工作流程将完全接受测试,其中所有依赖项(例如存储库)都被简单地剔除。
  • 您最终可能会在没有任何具体数据库/UI 实现等的情况下编写整个执行评估工作流程。所有业务逻辑都在此域服务中进行编排,并且所有逻辑都存在于您的评估实体和其他关联实体中。
  • 转到下一个用例 - 可能是用例 4 - 修改评估(再次执行与上述相同的操作)
  • 将外围设备(例如存储库/数据库、UI 等)保留到您的实现中尽可能晚。首先锁定域中的所有业务逻辑很重要 - 然后从域中消除外围问题 - 它更便宜/更有效(以我的经验)

  • 请注意,没有正确的方法可以做到这一点,这只是我通常如何处理上述项目的概要。这里的关键是域实际上是所有实现背后的驱动力......

    关于domain-driven-design - 真实世界的 DDD : Structuring the Domain Layer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5572607/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com