Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Domain driven design DDD中两个有界上下文之间的通信_Domain Driven Design_Cqrs_Domain Events_Bounded Contexts - Fatal编程技术网

Domain driven design DDD中两个有界上下文之间的通信

Domain driven design DDD中两个有界上下文之间的通信,domain-driven-design,cqrs,domain-events,bounded-contexts,Domain Driven Design,Cqrs,Domain Events,Bounded Contexts,我在域中几乎没有不同的有界上下文。CRUD操作的验证是在每个有界上下文中构建的 例如,仅当创建实体的人是组长时,我才能创建名为GAME的实体 在这个例子中,我有两个有界上下文(BC)。一个是游戏BC,另一个是用户BC。为了解决这个问题,在游戏BC中,在继续创建游戏之前,我必须向用户BC发出一个域服务调用,如IsGroupLeader() 我认为DDD不推荐这种通信方式。我也可以在游戏BC中使用用户实体,但我不想这样做,因为同一用户实体在不同BC的不同上下文中使用的方式不同 我的问题是: 我是否应

我在域中几乎没有不同的有界上下文。CRUD操作的验证是在每个有界上下文中构建的

例如,仅当创建实体的人是组长时,我才能创建名为GAME的实体

在这个例子中,我有两个有界上下文(BC)。一个是游戏BC,另一个是用户BC。为了解决这个问题,在游戏BC中,在继续创建游戏之前,我必须向用户BC发出一个域服务调用,如IsGroupLeader()

我认为DDD不推荐这种通信方式。我也可以在游戏BC中使用用户实体,但我不想这样做,因为同一用户实体在不同BC的不同上下文中使用的方式不同

我的问题是:

  • 我是否应该使用域事件,其中游戏BC必须向用户BC发送事件,询问用户的状态?使用这种方法,我不会进行类似于IsGroupLeader的同步调用,但名为的事件是\u group\u leader。然后游戏BC必须等待用户BC处理事件并返回状态。只有在用户BC处理事件后,游戏BC才会创建游戏实体

  • CQRS是我问题的解决方案吗


  • 欢迎任何想法。

    集成BCs时,您有几个选择。不鼓励呼叫外部BC的原因是,这要求两个BC同时运行。然而,这通常是可以接受的,并且比备选方案更简单。另一种方法是让游戏BC订阅来自用户BC的事件,并保留其所需数据的本地副本,在本例中,这些数据是关于用户是否为组长的信息。这样,当游戏BC需要确定一个用户是否是组长时,它不需要呼叫用户BC,它只读取本地存储的数据。这种替代方案的挑战是同步事件。您有权确保游戏BC从用户BC接收所有适当的事件。另一个挑战是如何处理,因为BCs在任何给定的时间点都可能稍微不同步


    CQRS在某种程度上与该问题正交

    为了解决您面临的问题,我们使用了一种多年来出现并被证明非常有效的建模模式。有界上下文是在语义单元之后定义的,在企业组织中,语义单元通常可以映射到特定的角色

    考虑到不同的角色面临不同的问题,因此说的语言略有不同(或完全不同),这一点应该是显而易见的

    因此,我们总是将与应用程序交互的角色建模为应用程序需求(基础架构、持久性、UI、本地化等)和业务规则(域)之间的连接点,并在不同的模块(即程序集或包)中对其进行编码


    至于你的第二个问题,CQR可以是一种编码你所描述的BC之间交互类型的方法,但我不喜欢在这种特定的上下文中使用它。

    我想我可能必须遵循一种不同的方法,将用户实体作为游戏BC的一部分(同一实体也是用户BC的一部分)。我将使用存储库从游戏BC中的db中读取IsGroupLeader标志。这样,对用户BC的依赖关系将被删除,无需与用户BC进行通信


    你觉得怎么样?

    以下是我的理由

    我认为游戏BC不知道“用户”,但它可能知道“玩家”

    如果游戏BC依赖于活动/当前玩家,则应在创建游戏BC实例时将其传递给BC

    例如

    现在你的两个BC仍然是分开的,你可以分别测试它们等等

    为了让这一切顺利进行,您只需执行以下操作:

     User currentUser = GetCurrentUser();
     Player currentPlayer = new Player();
     currentPlayer.IsGroupLeader = currentUser.IsGroupLeader;
     GameBC gameBC = new GameBC(currentPlayer);
     gameBC.DoStuff();
    
    这是UserBC和GameBC之间的一个反腐败层,您可以将想要的状态从UserBC移动到GameBC需要的状态并进行验证


    如果你的游戏BC需要访问许多用户,你仍然可以向游戏BC传递某种映射服务,在游戏BC内部进行这种转换。

    我想你差不多做到了。接近一个好的解决方案。我不确定你是否必须将这两个BC拆分为两个。你的用户聚合器(?)一个用户“拥有”一个或多个“游戏”的“成员资格”(仅猜测您的实体关系)。 但我现在只是头脑风暴。试着遵循:)不同的方法如下:

    首先 GameBC有一个Create()方法,它实际上将UserMembership作为参数。创建(用户成员资格)。 然后通过UserMembership实体了解这是什么类型的成员身份和用户。如果接受,则创建游戏。若并没有抛出异常,或者游戏收到一条违反规则的消息,这取决于你们想用什么方法和客户端通信。协调可以在应用层完成,而不会泄漏领域知识

    你做的和其他答案一样。在Game.Create(UserId)方法中引发CreateGameEvent。该事件由驻留在应用程序层的EventHandler(由IoC在应用程序启动中注册)捕获,并通过存储库查找用户成员资格。领域知识的一个小漏洞是,知道谁可以做什么的业务规则在应用层得到验证。这可以通过让CreateGameEventHandler获取UserId和RuleRef(可以是字符串“can_CREATE_GAME”或enum)并让UserPermission对象验证权限来解决。如果没有。异常被抛出并捕获
     User currentUser = GetCurrentUser();
     Player currentPlayer = new Player();
     currentPlayer.IsGroupLeader = currentUser.IsGroupLeader;
     GameBC gameBC = new GameBC(currentPlayer);
     gameBC.DoStuff();