Son*_*ate 11 domain-driven-design
我试图从以数据为中心的设计和开发跳转到DDD并阅读了Evans和Nillson,但我仍然无法理解我应该如何构建我的域层.我确信我当前项目的性质没有帮助!
一点背景
该应用程序是管理人员评估的内部解决方案.人力资源人员将创建评估"模板",其中包含一组问题,团队负责人和管理人员要为每个直接报告完成这些问题.答案将持续进行审核和审核.这些评估可以用于各种各样的事情,例如公司计划的反馈,绩效评估等.
以数据为中心的一面
不是为了影响解决方案而是突出我以数据为中心的思维方式,我已经对数据库架构有了一个愿景,并将其包含在这里仅供参考(因为图片说千言万语):
正如预期的那样,模式被标准化,并且与我的应用程序中的数据处理方式不匹配.而且,我已经省略了查找表等,试图将问题保持在最低限度.
用例
第一个用例是检索和显示用户需要完成的评估列表.这将在用户首次登录应用程序时显示,并且最初似乎相对容易,但有两个问题:1 - 评估是基于时间的,因此可能需要每月,每年或每个'x'根据员工周年日的年数; 并且,2 - 用户可以保存正在进行的评估并在以后完成.因此,列表应包含到期的评估以及正在进行的评估.
接下来,当用户选择要执行的评估时,我需要检索该评估的所有问题(当前版本),以便我可以将它们显示给用户.在评估期间的任何时候,用户可以保存当前结果.只有在整个评估完成后,才能实际"提交" - 或承诺.
第三,人力资源需要一种方法,通过主管提供的响应重新生成评估.
最后,人力资源部门能够创建和修改评估 - 并对其进行版本控制.因此,每当有人修改评估时,都会创建一个新版本,并且该版本将成为执行的任何新评估的模板(任何正在进行的评估将继续使用其原始模板).
领域模型
按顺序工作,对我来说,我将有一个评估实体,它是一个聚合根,以满足第四个用例.它将具有Section实体的子集合,而这些子集合将具有Question实体的子集合.他们都是实体,因为他们有身份(是吗?).评估是消费代码用于持久性,验证等的对象(尽管Section和Question实体验证自己并将状态汇总到根评估).我的目标是从消费者那里制作版本抽象,并在数据持久层中实现它(好的或坏的想法?)
这意味着我还将拥有一个为我处理持久性的AssessmentRepository,并且可能还有一个在需要时创建新评估的AssessmentFactory.
更大的问题来自其他用例.我是否还有EmployeeAssessment Aggregate root?或者它只是一个实体?
查看用例,我需要以两种方式使用此信息.首先,当我生成要向用户显示的评估列表时,我不仅要根据评估频率评估直接报告列表,而且还需要知道我是否已经开始和/或完成评估对那个雇员.这来自EmployeeAssessments表.另一种情况是当用户实际执行评估时,我正在与EmployeeAssessments和Responses表进行交互.
从UI的角度来看,当用户执行评估时,他们对内部数据结构等一无所知.我需要为UI提供该评估的问题列表,以显示并接受要保留的响应列表.这会导致第二个根带有附带的存储库等吗?
第三个用例类似,因为人力资源部门希望能够在以后通过回复重新生成评估.但是,我认为在执行评估时使用的相同过程可以在这里使用,因为恢复现有评估将需要相同的数据,唯一的区别是读/写能力与HR的只读.
把它包起来!
好吧,我已经絮絮叨叨地认为我已经清除了我的脑袋网.我欣赏任何方向,建议,批评等等.正如我所说,我正在试图跳跃并认为我理解这些概念,现在这是应用它们的问题.谢谢!!!
几年前我和你一样跳了起来.我现在正在从普通的香草DDD跳到CQRS(参见cqrsinfo.com/).
我会采用CQRS方式,即使用事件存储,并在架构级别完全分离读写.但是我认为你提到的问题更加符合普通的DDD方式 - 所以我将在这个背景下回答它.
你需要完全摆脱"数据驱动"的思考.从主要工作流程开始.第一次和第三次使用基本上只是获取操作.我将首先关注聚合根状态发生变化的用例.因此,使用案例2即"执行评估"将是一个很好的起点.
正如您正确指出的那样,聚合根将是评估.可以创建"PerformAssessmentService"类(相当于域服务),此处将存在执行评估工作流.此工作流程将完全处于测试状态,其中所有依赖项(例如存储库)都被简单地删除.
您可能最终编写整个执行评估工作流而没有任何具体的数据库/ UI实现等.所有业务逻辑都在此域服务中编排,并且所有逻辑都存在于您的评估实体和其他关联实体中.
转到下一个用例 - 也许用例4 - 修改评估(再次执行相同操作)
保留诸如存储库/数据库,UI等外围设备,直到您的实施中尽可能晚.重要的是首先锁定域中的所有业务逻辑 - 然后从域中驱动您的外围设备问题 - 它更便宜/更高效(根据我的经验)
请注意,没有正确的方法可以做到这一点,这只是我将如何处理上述项目的概要.这里的关键是域名实际上是实施所有内容的驱动因素......