How to simulate users and groups in DDD?

Except for the question of whether the following scenario is a good thing for DDD in general, I would like to discuss it and ask for advice:

Given that we have users and groups. The user has a name, and the group also has a name. Users can join vacation groups, and they can also change groups. Rules to which they must obey: A user can only be in a maximum of 2 groups, and a group can consist of a maximum of 10 users.

How do you model it? So far I can present three options, where each option has its own individual advantages and disadvantages:

  • Users and groups are entities, and both are aggregates. Join, Switchand Leaveare teams in the aggregate of groups. Although this is great for Joinand Leave(since they belong to only one group), this does not work for Switch, since it refers to two groups at the same time and, therefore, it is necessary to change two units in one transaction, which is not very nice.

  • Users and groups are entities, and both are aggregates. Join, Switchand Leaveare user aggregate commands. This works great for all three, and it’s easy to verify that a user cannot consist of more than two groups at a time, but how can you verify that the rule of maximum 10 users per group is not broken?

  • Users and groups are objects, both are aggregates. But there is a third aggregate: Relations. Join, Switchand Leavenow are teams in the aggregate of relations. Although this is apparently the best approach (as it gives the connection between users and groups a name and makes it explicit), now I completely lost the way of modeling constraints.

Can someone give me a hint?

If there was only one of two limitations, it would be easy: then you could put the commands in an aggregate that also has limitations. But if you have a restriction on both sides, I get lost. Any help?

+3
source share
1 answer

, , . , , , .

class Application
  handle(UserWantsToJoinGroup command)
    user = users.withId(command.userId)
    group = groups.withId(command.groupId)
    user.join(group)

class User
  join(Group g)
    if g.isFull throw
    if this.isMemberOf(g) throw
    if this.numberOfGroupsImIn >= 2 throw

    publish new JoinedGroup(this.userId, g.groupId)

  handle(JoinedGroup evt)
    // modify state

class Group
  handle(JoinedGroup evt)
    // modifiy state
+5

All Articles