简体   繁体   English

DDD 选择聚合根

[英]DDD Choosing Aggregate Roots

Building a time tracking application I am trying to determine the best way to design the aggregate roots.构建时间跟踪应用程序 我试图确定设计聚合根的最佳方法。

The basic core entities are Client, Project, Employee, ProjectAssignment, Department, Timesheet.基本的核心实体是 Client、Project、Employee、ProjectAssignment、Department、Timesheet。 A Client has one or more projects, a project has one or more employees assigned to it (via ProjectAssignment), an Employee belong to a department, and Timesheet links Project, Employee together.一个客户有一个或多个项目,一个项目有一个或多个员工分配给它(通过 ProjectAssignment),一个员工属于一个部门,时间表将项目、员工链接在一起。

Client seems like an obvious aggregate root.客户端似乎是一个明显的聚合根。

Client -> Project -> ProjectAssignment -> Employee

Regarding the other aggregates I'm kind of not sure what the best way to go would be...关于其他聚合,我有点不确定最好的方法是什么......

I was thinking...我刚在想...

Department -> Employee -> Person

Or have Employee and Department as separate aggregates entirely.或者将员工和部门完全作为单独的聚合。 Employees can be in one department and one department only.员工可以在一个部门,只能在一个部门。 However department is self referencing to create a department hierarchy.但是,部门是自引用以创建部门层次结构。

How do you deal with entities being shared between aggregate roots?您如何处理在聚合根之间共享的实体?

DDD is not about data structure nor the relationship between those structures, but about changes that happen on those data and the boundaries around those changes. DDD 不是关于数据结构,也不是关于这些结构之间的关系,而是关于发生在这些数据上的变化以及这些变化周围的边界。 DDD is very poorly explained in a lots of places, including Pluralsight courses or conferences, where people build a simple application, focused on single user, and try hard to impose as many DDD principles as they can. DDD 在很多地方都没有得到很好的解释,包括 Pluralsight 课程或会议,在那里人们构建一个简单的应用程序,专注于单个用户,并尽可能多地强加 DDD 原则。

Core principle in domain driven design is boundary.领域驱动设计的核心原则是边界。 When you try to find out Aggregates, first think of processes you perform in your application and what do you need to have, in order to make those processes consistent.当您尝试找出聚合时,首先要考虑您在应用程序中执行的流程以及您需要具备什么才能使这些流程保持一致。 Then build a single entity that performs this changes and wrap it with any other needed entities (values objects) in an aggregate.然后构建一个执行此更改的单个实体,并将其与任何其他需要的实体(值对象)一起包装在一个集合中。 Then promote one entity as a gatekeeper for all the processes that are executed with those entities.然后将一个实体提升为与这些实体一起执行的所有流程的看门人。

Starting design from data structure is number one reason why people fail at DDD.从数据结构开始设计是人们在 DDD 上失败的第一大原因。 From what you have provided, to me, it seems that your aggregate is rather a ProjectAssignment and maybe a Timesheet , because here probably will lay a core business logic.从您提供的内容来看,对我而言,您的聚合似乎更像是一个ProjectAssignment并且可能是一个Timesheet ,因为这里可能会奠定核心业务逻辑。 All the other things are barely a value objects (or entities if you must use ORM) that can be created with simple CRUD style approach.所有其他的东西都只是一个值对象(或者实体,如果你必须使用 ORM),可以用简单的 CRUD 风格的方法创建。 There are many discussions and blog posts about differences between entities and value objects.有很多关于实体和值对象之间差异的讨论和博客文章。 People tend to give some meaning to 'objects' they have in they domain, but for domain experts, those precious objects, that we spend so much time to create, are just values, nothing more.人们倾向于赋予他们领域中的“对象”一些意义,但对于领域专家来说,那些我们花费大量时间创造的宝贵对象只是价值,仅此而已。 So don't promote Client or Department as an aggregate root - they are just values.因此,不要将ClientDepartment提升为聚合根——它们只是值。

Don't fear to you use CRUD.不要害怕你使用 CRUD。 Many things you come across designing your domain will be just value object for domain exports.您在设计域时遇到的许多事情都只是域导出的值对象。 They just use them to perform operations on true business entities.他们只是使用它们对真正的业务实体执行操作。 They don't care how a Client is created, how a Department is created or how a Department hierarchy is created.他们不关心如何创建Client 、如何创建Department或如何创建Department层次结构。 They just create them and then edit them or delete them.他们只是创建它们,然后编辑或删除它们。 So the words used to describe a Client or a Department will be just create, update or delete - and those words are very poor candidates for the ubiquitous language (a domain language).因此,用于描述ClientDepartment将只是创建、更新或删除——而这些词对于无处不在的语言(领域语言)来说是非常糟糕的候选词。 Ubiquitous language is so much underrated pattern in DDD.无处不在的语言是 DDD 中被低估的模式。 When you use it properly it will save you a ton of time, which you spend designing things, that just don't matter for the business.当你正确使用它时,它会为你节省大量时间,你花在设计东西上,这对业务无关紧要。 Every time you think you need to create something or update something - use CRUD!每次您认为需要创建某些内容或更新某些内容时 - 使用 CRUD! Don't bother your self with DDD principles, because they simply don't apply when it comes to words like create or update.不要用 DDD 原则来打扰你自己,因为当涉及到诸如创建或更新之类的词时,它们根本不适用。

Bear in mind that DDD shines only in a collaborative domain and only when you have access to a domain expert.请记住,DDD 仅在协作领域中大放异彩,并且仅当您可以访问领域专家时。 It is really hard to have business expert and developer hat at the same time.同时拥有业务专家和开发人员的帽子真的很难。 At least make the design in group or at least in pair, try some event storming.至少让设计成组或至少成对,尝试一些事件风暴。 Creating a decent DDD design alone, will almost always fail, from my experience.根据我的经验,单独创建一个体面的 DDD 设计几乎总是会失败。

In designing Aggregates you should take into considerations the Bounded Contexts and the Invariants.在设计聚合时,您应该考虑有界上下文和不变量。 From what I understand you have brought into discussion only one Bounded Context.据我了解,您只讨论了一个限界上下文。 About the invariants you specified that an employee can be in only one departament.关于您指定的员工只能在一个部门工作的不变量。 From what I can tell the Aggregate roots (ARs) are: Client , Project , Employee and Department .据我所知,聚合根 (AR) 是: ClientProjectEmployeeDepartment

ProjectAssignment should be a value object in Project AR, that holds a list of Employment IDs and other data like assignment date. ProjectAssignment应该是Project AR 中的一个值对象,它包含一个 Employment ID 列表和其他数据,如分配日期。

Timesheet could be a value object inside Employee holding a list of Projects IDs and other data like start date and end date. Timesheet可以是Employee内部的一个值对象,其中包含Projects IDs和其他数据(如开始日期和结束日期)的列表。

Employee AR could hold a reference to its Department ID enforcing your invariant that an employee belongs in only one department. Employee AR 可以持有对其Department ID的引用,以强制执行员工仅属于一个部门的不变式。

When choosing an aggregate root you choose between Transactional Consistency and Eventual Consistency.选择聚合根时,您可以在事务一致性和最终一致性之间进行选择。 When your business rules allow you would rather favour Eventual Consistency.当您的业务规则允许时,您宁愿支持最终一致性。

Let's look at Employee and Department.让我们看看员工和部门。 Check against your use cases: is it ok to use eventual consistency for department/employee changes (would users agree to see an outdated orhanizational structure sometimes?)检查您的用例:是否可以对部门/员工变更使用最终一致性(用户是否同意有时会看到过时的组织结构?)

If yes treat Department and Employee as seperate aggregates.如果是,将部门和员工视为单独的聚合。 Make Employee reference Department through its id.通过其 id 使 Employee 引用 Department。

If it's not ok (eg user would not tolerate wrong deparment for employee in timesheet report) then make Department an aggregate holding a collection of Employee entities.如果不行(例如,用户不会容忍时间表报告中员工的错误部门),则使 Department 成为持有 Employee 实体集合的集合。

More on this topic you can find in IDDD book by Vaughn Vernon: https://www.amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/0321834577您可以在 Vaughn Vernon 的 IDDD 书中找到有关此主题的更多信息: https : //www.amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/0321834577

An "aggregate" is a cluster of associated objects that we treat as a unit for the purpose of data changes." Evans. 126 “聚合”是一组相关联的对象,我们将其视为一个单元,以便进行数据更改。”Evans. 126

The Aggregate Root is the main entity that holds references to the other ones. Aggregate Root 是保存对其他对象的引用的主要实体。 It's the only entity in the clump that is used for direct lookup.它是丛中唯一用于直接查找的实体。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM