DDD Choosing Aggregate Roots
Asked Answered
V

4

10

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. 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.

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?

Vorlage answered 9/3, 2017 at 19:42 Comment(0)
P
29

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 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.

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. 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. 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. 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.

Don't fear to you use 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. 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). Ubiquitous language is so much underrated pattern in 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! Don't bother your self with DDD principles, because they simply don't apply when it comes to words like create or update.

Bear in mind that DDD shines only in a collaborative domain and only when you have access to a domain expert. 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.

Phrase answered 13/3, 2017 at 21:22 Comment(5)
Very good answer! Would DDD apply in a long business processing engine (a few complex algorithms which run for minutes / hours), where user interaction is only a few inputs? Is this an example of non-"collaborative domain" problem?Nucleonics
Short answer: no. DDD is a tool to design software not to implement it. You can of course always use all the artifacts or patterns it brings (as they have value on their own). When you are implementing algorithms it is better to use common sense: procedural mindset or oop mindset with some design patterns, because humans that will interact with your code (i.e: read it later or fix) will be developers, not business people. To sum up: DDD is a design tool to create code that is easy to read for people who talk in business language.Phrase
First off, great answer. For laughs because you commented that it is so poorly taught -- imo it's because language is so sensitive in technical fields, I just wanted to point out the kinds of statements that makes this subject so hard to teach "Then build a single entity that performs this changes and wrap it with any other needed entities (values objects) in an aggregate. " ...Richella
... While I know what you were actually saying (the aggregate is a conceptual boundary, not a physical boundary), after reading that line, my mind immediately went to creating a class that physically wrapped/contained the aggregate root which is totally wrong. Anyway, I found it amusing.Richella
your answer and comments are all that is right.Mond
V
3

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.

ProjectAssignment should be a value object in Project AR, that holds a list of Employment IDs and other data like assignment date.

Timesheet could be a value object inside Employee holding a list of Projects IDs and other data like start date and end date.

Employee AR could hold a reference to its Department ID enforcing your invariant that an employee belongs in only one department.

Valentinvalentina answered 9/3, 2017 at 21:8 Comment(0)
B
1

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.

If it's not ok (e.g. user would not tolerate wrong deparment for employee in timesheet report) then make Department an aggregate holding a collection of Employee entities.

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

Bidle answered 20/3, 2017 at 8:10 Comment(0)
N
0

An "aggregate" is a cluster of associated objects that we treat as a unit for the purpose of data changes." Evans. 126

The Aggregate Root is the main entity that holds references to the other ones. It's the only entity in the clump that is used for direct lookup.

Numbat answered 4/4, 2020 at 13:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.