域驱动设计 – Real-World DDD:构建域层

我试图将以数据为中心的设计和开发转变为DDD,并阅读了Evans和Nillson,但是我仍然无法围绕我如何构建我的域层.我相信我目前的项目的性质并没有帮到!

有一点背景

该应用程序是管理人员评估的内部解决方案.人力资源人员将创建评估“模板”,包括团队领导和管理人员为每个直接报告完成的一系列问题.这些答案坚持审计和审查.这些评估可以用于各种各样的事情,例如公司计划的反馈,绩效评估等.

我以数据为中心的一面

不影响解决方案,但强调以数据为中心的心态,我已经有了数据库架构的愿景,并将其包含在此仅供参考(因为图片说了一千个字):

正如预期的那样,模式被规范化,并且与我的应用程序中的数据处理方式不一致.而且,我已经省略了查找表等,以尽量减少手头存在的问题.

用例

一个用例是检索和显示用户需要完成的评估列表.这将在用户首次登录应用程序时显示,最初似乎相对容易,但有两个皱纹:1 – 评估是基于时间的,因此可能需要每月,每年或每个“x”以雇员周年日为准的年数;并且,2 – 用户可以节省正在进行的评估,并在以后完成.因此,该清单应包含到期以及正在进行的评估.

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

第三,人力资源需要通过主管提供的回应来重新产生评估.

最后,人力资源部门能够创建和修改评估 – 并将其进行版本控制.因此,每当有人修改评估时,都会创建一个新版本,并将其作为执行的任何新评估的模板(任何正在进行的评估将继续使用其原始模板).

域模型

工作不合理,对我来说,我将有一个评估实体是一个总体根,以满足第四个用例.它将有一个小组收集的部分实体,反过来又会有一个问题实体的子集.他们都是实体,因为他们有身份(是?).评估是消耗代码用于持久性,验证等的对象(尽管部分和问题实体验证自身并将状态汇总到根评估).我的目标是使消费者的版本抽象实现在数据持久层(好的或坏的想法?)

这意味着我还将有一个AssessmentRepository来处理我的持久性,并且可能需要一个EvalFactory来创建一个新的评估.

更大的问题来自其他用例.我有一个EmployeeAssessment聚合根?还是简单的一个实体?

看一下用例,我需要使用这些信息几种方法.首先,当我生成评估列表以显示用户时,我不仅要评估直接报告的列表,而且还需要了解我是否已经开始和/或完成了评估为该员工来自EmployeeAssessments表.另一种情况是当用户实际执行评估时,在这种情况下,我正在与EmployeeAssessments和Responses表进行交互.

从UI的角度来看,当用户执行评估时,他们什么也不了解内部数据结构等.我需要为UI提供该评估的问题列表,以显示并接受持续的响应列表.这是否带有附带存储库等的第二根?

第三个用例是类似的,因为人力资源部希望能够在稍后的日期通过响应重新生成评估.然而,我认为在执行评估时使用的相同过程可以在这里使用,因为恢复现有评估将需要相同的数据,唯一的区别是读/写能力与只读HR.

已经包装了!

好吧,我已经漫游了,我想我已经清除了我的骷髅网.我感谢任何方向,建议,批评等.正如我所说,我正在尝试跳跃,并认为我理解的概念,现在是一个应用它们的问题.谢谢!!!

几年前我和你一样跳了起来.我现在正在从普通的香草DDD跳到CQRS(见cqrsinfo.com/).

我会接受这种CQRS的方式,即使用事件存储和完全独立于从架构层面写入的读取.不过我认为你提到的问题更符合普通的香草DDD方式 – 所以我将在这个上下文中回答.

你需要完全摆脱“数据驱动”的想法.从主要工作流程开始.第一个和第三个使用本质上只是获取操作.我将首先集中在根状态变化的用例.因此,使用案例2即“执行评估”将是开始的好地方.

正如你正确地指出的那样,聚合根将是评估.可以创建“PerformAssessmentService”类(相当于一个域服务),并且您的执行评估工作流将存在于此处.这个工作流将完全被测试,其中所有依赖关系(如存储库)都被简单地删除.
>您可以最终编写整个执行评估工作流程,而无需任何具体的数据库/ UI实现等.所有业务逻辑都是在此域服务中编排的,所有逻辑都存在于评估实体和其他关联实体中.
>移动到下一个用例 – 也许使用情况4 – 修改评估(再次执行上述操作)
>留下周边的东西,如仓库/数据库,UI等,直到你的实现尽可能晚.首先锁定您的域中所有业务逻辑的重要性 – 然后从域中驱动您的外围关注 – 它的成本更低/更高效(在我的经验中)

请注意,没有正确的方法来做到这一点,这仅仅是我将如何处理上述项目的概要.这里的关键在于,域名实际上是所有实施的驱动程序…

相关文章

迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图...
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,...
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定...
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个...
命令模式(Command)命令模式(Command)[Action/Transactio...
生成器模式(Builder)生成器模式(Builder)意图:将一个对...