Search code examples
architectureaggregatedomain-driven-designsoftware-design

DDD Aggregate Modeling Invariant


I am modeling a relation between an enterprise group its companies and the companies' users and right away I have an invariant that requires my aggregate to become enormous :(.

I need to verify that when adding a user to a company, that user is unique across the whole group. My initial idea was to have an aggregate "group -> companies -> users" but it becomes too big and poses concurent modification issues.

I was thinking that maybe I can create a second representation of the Group that contains just the list of IDs of all its users and only this special aggregate has the "addUser" method.

Is this the right approach ?

Reading Eric Evans and Vaughn Vernon I get the idea that I might need "eventual consistancy" since my invariant spans across aggregates.

Any ideas and comments are greatly appreciated ! Thank you !


Solution

  • I was thinking that maybe I can create a second representation of the Group that contains just the list of IDs of all its users and only this special aggregate has the "addUser" method.

    Yes - that's the right idea.

    The problem is set validation, and the answer is that to maintain an invariant over a set, you need to be able to lock that set to prevent concurrent modification. In an "aggregate" design, that means that the entire set needs to be contained in a single aggregate.

    When you have a single aggregate that is a bunch of information that you need for set validation (but not other operations) and a bunch of information used for other operations (but not validating the set), conventional wisdom is to split the set and its supporting operations into a separate aggregate.

    There are a couple things to keep in mind:

    First, when the invariant you are concerned with is "uniqueness", you may be able to model the domain using many small sets rather than one big one. For example, you might be able to use the userId as a key that fetches a set with zero elements (user not yet assigned) or one element (user is assigned to a specific company within a group).

    Second, pay careful attention to:

    What is the business impact of having a failure

    If the cost of an invariant failure is small, then a best-effort-plus-detect-and-correct strategy may be more cost effective than implementing countermeasures to prevent the possibility of failure.