我想你快到了。接近一个好的解决方案。我不太确定您是否必须将这两个分成两个 BC。您的 User Aggregateroot (?) 和 Game 可能属于一个 BC 并相互依赖。用户“拥有”一个或多个“游戏”的“会员资格”(只是猜测您的实体关系)。但我现在只是在头脑风暴。尝试遵循:) 不同的方法如下:
第一个
GameBC 有一个 Create() 方法,它实际上将 UserMembership 作为参数。创建(用户会员)。然后你通过 UserMembership 实体知道什么样的成员资格和用户这个。如果接受,则创建游戏。如果未引发异常或 Game 收到错误规则消息,则取决于您要与客户端通信的方法。协调可以在应用层完成,而不会泄露领域知识。
其次
,您可以作为其他答案之一。您在 Game.Create(UserId) 方法中引发了 CreateGameEvent。该事件由驻留在应用程序层中的 EventHandler(由 IoC 在应用程序启动中注册)捕获并通过存储库查找 UserMembership。领域知识的小泄漏是知道谁被允许做什么的业务规则在应用层进行了验证。这可以通过让 CreateGameEventHandler 获取 UserId 和 RuleRef(可以是字符串“CAN_CREATE_GAME”或枚举)并让 UserPermission 对象验证权限来解决。如果不。异常在应用层被抛出和捕获。缺点可能是您不希望在 Create 方法中对权限引用字符串进行硬编码。
第三
...在第二种方法结束的地方继续。您知道如果您遵循 SRP 原则,GameBC 可能不是进行用户权限查找的正确位置。但是该操作以某种方式围绕该方法触发。另一种方法是创建(GroupLeader 用户)。或者你可以让 Game.Create(User user) 然后验证 User 是 GroupLeader 类型。Create(GroupLeader) 告诉你调用这个方法需要什么。
最后
也许是我现在写这篇文章时更喜欢的替代方案。当你想创建一个实体时,我通常让 Create(Save) 方法在存储库中。IGameRepository 接口位于域组装项目中的游戏实体旁边。但是您也可以创建一个负责启动游戏实体生命周期的 GameFactory。这里也是放置 Create 方法的好地方... GameFactory.Create(GroupLeader) { return new Game.OwnerUserId = GroupLeader.Id; 然后你只需保存它 IGameRepository.Save(Game)
然后你就有了一种直观和自我描述的方式来告诉其他开发人员“你必须有一个 GroupLeader 实例才能创建一个游戏”。
最后,我希望您意识到您了解该领域,并且您会找出最适合您的领域。务实一点,不要硬核 Eric Evan。有这么多的开发者被困在如何完成事情的“宗教”中。项目的大小、资金、时间和对其他系统的依赖等也会影响您在执行 DDD 时的严格程度。
祝你好运。