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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With