I've recently been delving into DDD resources (books--Vaughn Vernon's--and other online resources) and in my attempt to do two things at once (work on a pet project and apply what I've been learning) I found myself stuck at a point where I have to make a decision about how aggregates and entities are created, while maintaining invariants and not break the rule about transactional consistency for one aggregate at a time.
Domain representation
In my domain I can have an aggregate root that we can call Container
, which contains some metadata properties and a list of ids for referencing another aggregate, let's call this one 'Document'. Both of these will be editable independently of eachother, so it makes sense to have them as separate aggregates. To change the Document
I don't have to update the Container
and vice-versa.
For me, an empty Container
does not make sense. When you create it, there needs to be at least one Document
in it. I was thinking of providing it by default.
Having this rule means that when I create a new Container
in order for it to be in a valid state, it needs at least one Document
id. To create a Document
you need to assign it its parent id, the Container
. So now I feel I have chicken and egg problem.
Things I've considered
I could get a new id from the Container
repository and create that child Document
with it as its parent, then create a Container
with the same id and pass the Document
id as a "child". This would be done within a DomainService method, which is what some recommend to maintain consistency between multiple aggregates. This feels like braking the rule of "one aggregate" at a time.
I could create a new Container
, publish an event that it was created, then a subscriber would create a "default" Document
and assign it to the Container
. This seems like a good way of doing it, but if the second event is not properly handed I end up with an empty/invalid-state `Container.
Do I treat the Container
as a kind of a tag and not make it an aggregate? basically flipping the whole thing over? A Document
then would be center stage, so when I create a Document
I need to assign/create a ContainerId
(tag)... Listing would then be a bit more cumbersome, since you'd have to keep track of all ContainerId
form all Documents
.
To make matters worse, a Document
can have referential ids for other entities (I'm still deciding if it's worth making those value objects, even though it feels to me like they have life-cycle--can get updated over time), which also has this rule of "at least one".
Any suggestions? Am I modelling this wrong? Are my concerns valid, but shouldn't pose a problem in this particular case? Any help would be much appreciated!
I have so many questions! but I'll stop here.
Visual aid