【问题标题】:DDD Composing Multiple Bounded ContextsDDD 组合多个有界上下文
【发布时间】:2015-04-23 16:58:35
【问题描述】:

我想听听您关于有界上下文集成的建议。 我有一个用例让我陷入困境:

  • 我有一个用于Contract 管理的有界上下文。我可以将各方(例如各种外部组织)添加到合同中。为每一方选择他们的投资/贡献(例如:总额的 10%)。 SO 合同管理有两个方面:一个是行政管理(添加当事人,管理多个日期,...),另一个是财务(计划他们跨越多年的供款,检查供款消耗,...)。
  • 我有另一个Budget 的有界上下文。此上下文负责组织级别的费用管理。示例:服务 A 将具有 1000 欧元的费用容量。我们可以计划预算,然后每个组织方都可以消费,购买东西,他们的一部分。为了建立预算,负责企业预算的用户可以直接分配资金或整合年度合同财务组件。当我们将合同部分集成到预算中时,我们冻结了预算中的数据,即我们将货币数据从一个数据库表复制到另一个数据库表中(添加一些审计信息)。我们只有一个数据库。

这是我挣扎的最后一部分。每个有界上下文都是一个专用应用程序。在budget 应用程序中,在当前预算中集成了合同部分后,我需要显示预算明细行。不幸的是,在预算表中,我只有金钱数据,没有关于合同的一些基本信息(对象、参考、...)。

我在想什么:

  • 有时在有界上下文之间复制数据也不错。我冻结了合同中的金钱部分。我还可以冻结/复制合同的对象和引用。那么查询将只发生在budget context 内。但这里的问题是数据重复。今天我需要对象/引用,如果明天我需要更多字段......我将需要领域事件管理来保持合同/预算之间的数据同步。
  • 查询预算并为每一行查询一个contract 服务,该服务将返回所需的数据。这使每个上下文保持自主,但我需要发出大量数据库请求来丰富 budget details line 对象。
  • 只需在数据库级别进行一次连接,我们就可以完成这项工作。在这里耦合怎么样?这是简单的解决方案,也是我们今天正在做的事情(它是共享内核吗?)。如果不重新构建预算应用程序,我们似乎无法更改contract 结构。我在上下文之间没有程序化合同。

我的问题是:

如何构建需要来自 budget context 的数据的 UI 屏幕,并且每个详细信息行都需要来自 contract context 的数据?

旁注:

  • 也许从一开始上下文识别和周界就错了(这是一个遗留设计)。
  • 我希望保持上下文分离(松散耦合)。如果我们可以在上下文之间指定设计契约,那么维护会更容易(或者不是?)。
  • 我看不到如何集成这些上下文(我需要重新读取共享内核、ustream / 下游等)。

【问题讨论】:

  • 这是一个额外的、不同的有界上下文。它与现有的有界上下文有一些重叠,这很容易导致您走错路(合并上下文或将其他行为放在不属于它的上下文中)。
  • 请问您将如何为这个新的第三个上下文建模? (移动其中的所有域逻辑并查询它?)。这个新的上下文也将面向budget。它增加了复杂性。我理解你的评论。我会考虑它以及这种情况如何出现。在实现 DDD 时,Vernon 谈到了它,但没有提供示例:/ 我感觉很赤裸裸!
  • 我将评论扩展为答案。

标签: domain-driven-design


【解决方案1】:

这是一个额外的、不同的有界上下文。它与现有的有界上下文有一些重叠,这很容易导致您走错路(合并上下文或将其他行为放在不属于它的上下文中)。

有时可以在不同的有界上下文中拥有引用相同逻辑实体的实体,但它们只是为特定场景(例如在特定上下文中)提供该实体的不同视图。

电子商务场景就是一个很好的例子。在大多数电子商务应用程序中,您将拥有Order 的概念,但没有关于“订单”是什么的全球性、明确的概念。在金融环境中 - 订单只是一张发票。在履行环境中 - 订单只是一个装箱单和一个将货物发送到的地址。在营销环境中 - 订单代表了关于客户感兴趣的一点点情报,可用于未来的定向营销。

有一条贯穿所有这些实体的共同点,但您可能会看到至少 3 个独立的 Order 类,每个类都捕获上下文中的顺序的概念

所以在你的例子中,你有一个Contract 的有界上下文和Budget 的有界上下文。在我看来,你现在有另一种看待这些实体的方式,特别是它们相互作用的方式。这是实体的新视图,可以在其自己的上下文中捕获的视图。这个新的上下文可能会有自己的ContractBudget 实体,并且会与上下文和预算上下文重叠,但其中也会有其他关系和行为,这在其他上下文中没有意义上下文。

这是一个很难解释的想法 :) 前段时间我在这里写了一个类似问题的答案:DDD - How to design associations between different bounded contexts

【讨论】:

  • 非常感谢。我想过这个问题。它让我想起了 Evans 使用的 Book 示例(存在一个不同的书类并遵循书的生命周期:草稿、编辑……)。但是在这个例子中,我一直认为它是一个不同的逻辑实体(在数据库意义上是逻辑的:不同的表),并且使用域事件这些实体保持同步。当您谈论逻辑实体时,您是在谈论同一个数据库表,对吗?
  • @Archange 这是可能的,但存储库应该抽象出这些细节。自然,当我们处理一个新的上下文时,它应该有一个新的存储库。在 DB 术语中,你可以说这个上下文封装了两个表之间的连接,但我们尽量不让 DB 模式影响我们对域的理解 :)
  • 我同意你关于数据库抽象的观点。我在考虑微服务架构 [Fowler] 以及从头开始重建微服务的能力。只要它与其他微服务的合同得到履行,一切都很好。但是,如果我们使用在数据库级别连接 2 个表的新存储库构建 BC。难道我们在 DB 级别上没有高度耦合:如果不重建 3 BC,我们就无法更改 DB 结构(重命名列)。我希望避免这种情况。也许我错了。
  • @Archange 如果在 OOP 中将事物封装到类中,那么在调用类上的方法的任何地方都会有“耦合”,因为被调用者需要知道签名。这并不意味着使用封装不好。这只是意味着您已经从耦合逻辑转移到“耦合”接口,这很好,因为这就是接口的用途。对于 BC,可以共享消息或基本 DTO。两个 BC 都不会知道另一个 BC 将它用于什么。所以它们在高层次上是解耦的,这就是你想要的。但可以肯定的是,它们仍然依赖于彼此的接口。
猜你喜欢
  • 1970-01-01
  • 2011-05-30
  • 2012-10-16
  • 2013-11-27
  • 2021-02-23
  • 1970-01-01
  • 2014-08-22
  • 1970-01-01
  • 2021-05-28
相关资源
最近更新 更多