关于领域驱动设计:如何在 DDD 中对用户和组进行建模?

 2022-01-08 

How to model users and groups in DDD?

除了以下场景是否适合DDD的问题,我想讨论它并寻求建议:

Given we have users and groups. A user has a name, and a group has a name as well. Users may join of leave groups, and they may also change groups. The rules they have to obey are: A user may only be in maximally 2 groups, and a group may consist of maximally 10 users.

你是如何建模的?到目前为止,我可以想到三个选项,每个选项都有其各自的优点和缺点:

  • 用户和组是实体,两者也是聚合体。 JoinSwitchLeave 是组聚合上的命令。虽然这对 JoinLeave 很有效(因为它们只引用一个组),但它不适用于 Switch,因为它同时引用两个组,因此需要修改两个聚合在单个事务中,这不是很好。

  • 用户和组是实体,两者也是聚合体。 JoinSwitchLeave 是用户聚合上的命令。这对所有三个都适用,并且很容易检查一个用户是否同时在两个以上的组中,但是您如何检查每个组最多 10 个用户的规则是否被违反?

  • 用户和组都是实体,都是聚合体。但还有第三个蕴:关系。 JoinSwitchLeave 现在是关系聚合上的命令。虽然这似乎是最好的方法(因为它为用户和组之间的关系命名并使其明确),但我现在完全不知道如何对约束进行建模。

  • 谁能给我一个提示?

    如果只有两个约束中的一个,那就太容易了:然后你可以把命令放到也有约束的聚合中。但是,如果您对双方都有约束,那我就迷路了。有什么帮助吗?


    您可以将一个组的实例交给用户,让它检查包含聚合的不变量。然后让用户知道它加入了群组,并让群组知道有用户加入。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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