如何在DDD中为用户和组建模?

Gol*_*den 3 domain-driven-design

除了下面的场景是否适合DDD的问题之外,我想讨论它并征求意见:

鉴于我们有用户和组.用户具有名称,组也具有名称.用户可以加入休假组,他们也可以更改组.他们必须遵守的规则是:用户最多只能有2个组,而一个组最多可以包含10个用户.

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

  1. 用户和组是实体,两者都是聚合.Join,Switch并且Leave是组聚合的命令.虽然这很适合JoinLeave(因为它们只引用单个组),但它不起作用Switch,因为它同时引用两个组,因此需要在单个事务中修改两个聚合,这不是很好.

  2. 用户和组是实体,两者都是聚合.Join,Switch并且Leave是用户聚合上的命令.这适用于所有三个,并且很容易检查用户同时不在两个以上的组中,但是如何检查每组最多10个用户的规则是否未被违反?

  3. 用户和组是实体,都是聚合.但也有第三个聚合:关系.Join,SwitchLeave现在命令的关系总和.虽然这似乎是最好的方法(因为它给用户和组之间的关系一个名称并使其明确),我现在完全迷失了如何建模约束.

任何人都可以给我一个提示吗?

如果只有两个约束中的一个,那将很容易:然后你可以将命令放到也具有约束的聚合中.但如果你对双方都有约束,那我就输了.有帮助吗?

Den*_*aub 5

您可以将组的实例交给用户,以使其检查包含聚合的不变量.然后让用户知道它加入了该组,并让该组知道用户已加入.

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
Run Code Online (Sandbox Code Playgroud)

  • 如你所说.在几微秒内,另一个用户加入的可能性有多大.如果它发生,它是否重要.这里最重要的模式:*询问领域专家*.他/她是否允许超量预订?或者他/她是否希望最后一次预订被回滚(使用传奇)?或者他是否愿意通知手动决定?我敢打赌,你看到它的发展方向. (2认同)