I would like to model the following entities: "Person", "Company" and the aggregate that ties the two together "Membership". I have identified that Person and Company are aggregate roots. Thus, "Membership" would hold a reference (id) of both those aggregate roots, plus other value objects/entities that a membership holds (for example the title that the person has for that company).
In my architecture I have the following layers: Api controllers, services, domains, repository. When creating a Membership object, the controller receives two identifiers (for person and for company). Currently the service is responsible for making a call to the CompanyService - to ensure that a company with that id exists and to the PersonService - to ensure a person with that id exists. However, in the Domain model I currently have a constructor that takes in two ids, which makes it feel really anemic. Also, in a further iteration, there will be the addition of a list of references to a third aggregate root, Vehicle. Thus a vehicle can exist by itself, or it can also belong to a membership.
Is this a bad way of modelling these entities? Is there a better way? I have read about the notion of domain services and application services, but my application does not currently have that distinction and I don't know if that concept would help in this case.
Even the behaviour of the aggregate roots feels a bit dry when it comes to functionality related to the other aggregate roots it holds references for: ie. the Membership domain model would have the ability to "Link a car", setting a car for itself, but again, receiving just an identifier that it would add to a list of identifiers.
A
) to directly reference another aggregate (B
) would be to allow for the former to invoke a method on the latter as part of it's own process (an aggregate's state is private after all). That is, the method body ofA->doSomething
would invokeB->doAnotherThing
. This is not useful and can be refactored toA->doSomething(B)
.A
andB
can be loaded independently and coordinated to achieve the above. The result is a cleaner (simpler) system.Membership
is the right name here? DDD asks you to model a system according to behavior. Notably, the above contains a lot of "this has that"-type phrases in lieu of "this does that"-type phrases. Of course this will lead to an anemic model. I'll leave you with some food for thought: When I (Person
) joined my golf course (Company
) I became aMember
that canreserveGolfCart
.