I'm trying to use the Repository pattern for my current project and i'm currently in the process of trying to model the domain and find the aggregate roots.
I've read of the 'Cascading Delete' rule which states that if it doesn't make sense to delete a member when the root is deleted then it shouldn't be part of the root.
I'll use a Police incident as an eample :-
Incident (Aggregate root) - This could contain investigating officers, notes made by each officer. It could also contain suspects with a list of dates that were interviewed. Was CCTV footage obtained for the incident? A log of each time the CCTV was viewed and by who? Were copies made of the CCTV for evidence/court etc
It seems like the IncidentAggregate could become huge since it appears that everything hangs on that incident.
My question is twofold, how much should the aggregate root manage and, are roots within roots a good idea?
This may not be a particularly good example since you'd probably never remove something like a police incident but i hope it describes my question better.
An aggregate usually contains references to other aggregate roots. These references should be deleted when the containing aggregate is deleted, but the aggregates they point to would remain.
To use your analogy. A report we shall assume is a part of only one incident aggregate, and would deleted along with the aggregate. No other aggregate would directly access these reports.
However, the incident aggregate would reference aggregates representing officers, and suspects, and CCTV viewing logs entries.
An aggregate is a group of objects with the same lifecycle.
If you deleted an incident would you also want to delete the investigating officer? No – if you did you’d soon have no policemen left. The investigating officer is not in the incident aggregate.
Of the other things you list, suspects, interviews, CCTV etc. The answer is – it depends.
It depends on your problem domain. What is your system doing? what is its scope? what problem is it solving?
If it’s only job is to track a string of incidents and assuming suspects, interviews and CCTV are only in the system as a result of a single incident, then yes, having them all in one aggregate could be appropriate. If the incident is deleted the suspects, interviews and CCTV can go.
If, for example, your also tracking archives of CCTV footage collected from a network of city centre cameras. Maybe your trying to monitor their effectiveness and reliability. If so you need to treat CCTV footage differently. It would be in a different aggregate with its own lifecycle. If you delete an incident you still want to keep your CCTV footage for other incidents and performance metrics.
What is in and out of an aggregate depends on your problem domain. Or more precisely it depends on the way you’ve modelled the problem domain solution.
Think lifecycle.
"Are roots within roots a good idea?"
Short answer in my opinion is no. As Kurt says, you should keep references to other aggregates. Just to be clear, by references I mean identifying objects. So perhaps your Incident aggregate would have a property such as
public IEnumerable<Guid> InvestigatingOfficerIds
{
get { return _investigatingOfficerIds.AsReadOnly(); }
}
Or
public IEnumerable<OfficerReference> InvestigatingOfficerIds
{
get { return _investigatingOfficerIds.AsReadOnly(); }
}
Whereby OfficeReference is a class that represents the value of an officers identity (under the hood would probably be a Guid).
If your domain logic needed to perform actions using both the Incident and investigating officers you would abstract this logic to a domain service and use the IOfficerRepository to fetch the officer aggregates using the IDs provided on the incident aggregate.
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