构建时间跟踪应用程序我正在尝试确定设计聚合根的最佳方法。
基本核心实体是Client,Project,Employee,ProjectAssignment,Department,Timesheet。客户有一个或多个项目,项目有一个或多个员工(通过ProjectAssignment),一个员工属于一个部门,时间表将项目,员工链接在一起。
客户端似乎是一个明显的聚合根。
Client -> Project -> ProjectAssignment -> Employee
关于其他总量,我有点不确定最好的方法是什么......
我在想......
Department -> Employee -> Person
或者将员工和部门完全作为单独的聚合。员工只能在一个部门和一个部门。但是,部门是自引用以创建部门层次结构。
如何处理聚合根之间共享的实体?
答案 0 :(得分:6)
DDD不是关于数据结构,也不是关于这些结构之间的关系,而是关于这些数据发生的变化以及这些变化的边界。 DDD在很多地方都很难解释,包括多个视觉课程或会议,人们构建一个简单的应用程序,专注于单个用户,并努力尽可能多地强加DDD原则。
域驱动设计的核心原则是边界。当您尝试查找聚合时,首先要考虑您在应用程序中执行的进程以及您需要具备的进程,以使这些进程保持一致。比构建执行此更改的单个实体并将其与聚合中的任何其他所需实体(值对象)一起包装。然后将一个实体提升为使用这些实体执行的所有进程的网守。
从数据结构开始设计是人们在DDD失败的首要原因。
根据您提供的内容,对我来说,您的聚合似乎是ProjectAssignment
而且可能是Timesheet
,因为这可能会构成核心业务逻辑。所有其他的东西几乎都不是值对象(或者如果你必须使用orm的实体),可以使用简单的crud样式方法创建。关于实体和价值对象之间的差异有很多讨论和博客文章。人们倾向于给对象提供一些意义。他们拥有域名,但对于域名专家而言,我们花费大量时间创建的那些珍贵物品,仅仅是价值,仅此而已。因此,不要将Client
或Department
作为聚合根宣传 - 它们只是价值观。
Client
,如何创建Department
或如何创建Department
层次结构。他们只是创建它们然后编辑或删除它们。因此,用于描述Client
或Department
的词语只是创建,更新或删除 - 而且这些词语是普遍存在的语言(域语言)的非常差的候选词。无处不在的语言在DDD中是如此被低估的模式。如果你正确地使用它,它将为你节省时间,你花在设计的东西,这对业务不重要。每次你认为你需要创造一些东西或更新一些东西 - 使用crud!不要用DDD原则来打扰自己,因为在创建或更新等词语时,它们并不适用。
请记住,只有在您可以访问域专家时,DDD才会在协作域中闪耀。同时拥有业务专家和开发人员帽子真的很难。至少将设计分组或至少成对,尝试一些事件风暴。根据我的经验,单独创建一个像样的ddd设计几乎总是会失败。
答案 1 :(得分:0)
在设计聚合时,您应该考虑有界上下文和不变量。
据我所知,你只讨论了一个有界上下文。
关于您指定的不变量,员工只能在一个部门中。
据我所知,聚合根(AR)是:Client
,Project
,Employee
和Department
。
ProjectAssignment
应该是Project
AR中的值对象,其中包含就业ID列表和其他数据,如分配日期。
Timesheet
可以是Employee
中的值对象,其中包含Projects IDs
列表以及其他数据,如开始日期和结束日期。
Employee
AR可以引用其Department ID
强制执行员工只属于一个部门的不变量。
答案 2 :(得分:0)
选择聚合根时,您可以在“事务一致性”和“最终一致性”之间进行选择。当您的业务规则允许您更愿意支持最终一致性。
让我们来看看员工和部门。检查您的使用案例:是否可以使用部门/员工变更的最终一致性(用户是否同意有时会看到过时的orhanizational结构?)
如果是,则将部门和员工视为单独的聚合。通过其ID创建员工参考部门。
如果不正常(例如,用户不能容忍时间表报告中员工的错误部署),那么请将部门作为持有员工实体集合的聚合。
有关此主题的更多信息,请参阅Vaughn Vernon的IDDD书籍: https://www.amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/0321834577
答案 3 :(得分:0)
“集合”是关联对象的集群,出于数据更改的目的,我们将其视为一个单元。” 埃文斯126
聚合根是持有其他引用的主要实体。它是丛中唯一用于直接查找的实体。