【问题标题】:DDD: one bounded context or two?DDD:一个或两个有界上下文?
【发布时间】:2012-10-16 19:13:50
【问题描述】:

假设我已经为我的客户构建了一个系统,让赌徒可以维护赌注组合并随着时间的推移跟踪他们的收益/损失。 该系统支持许多复杂的领域逻辑 - 投注不同的体育项目、将胜利滚动到其他投注等。

接下来,我的客户想要支持提示者的想法。提示者实际上并不赌博,而是他们 创建“提示表”,这是他们关于下注的提示。提示表可以是不同的 种类 - 有些可以包括任何可投注赛事的提示,其他仅提供有关赛马的提示,等等。 我的客户希望系统以与跟踪提示者表现相同的方式跟踪提示者的表现 赌徒,还可以比较不同类型的情报员内部和之间的表现(例如,谁是最好的赛马情报员?他们通常比足球情报员表现更好吗?)

现在,赌徒和推销员之间的领域语言完全不同,还有额外的 赌徒投资组合不存在的提示表分类。这表明这些是单独的有界上下文。 但是,它们有很多共同的逻辑,因为它们都随着时间的推移跟踪性能。

所以我的问题是:

  1. 这些真的是独立的有界上下文吗?我对在赌徒的上下文中添加分类持谨慎态度(感觉就像一个滑坡)。
  2. 如果它们是不同的上下文,我应该:
    • 在它们之间共享性能跟踪逻辑(即共享 DLL、jar 等)?这会在感觉错误的上下文之间创建紧密的实现耦合。
    • 将性能跟踪逻辑留在赌博有界上下文中,将分类逻辑置于提示者边界上下文中,并要求赌博上下文跟踪性能?在这种情况下,提示者上下文似乎会将命令发送到赌博上下文,这又让人感觉不对(我更喜欢事件)。
    • 做其他事情...某种组合层在两个上下文之间进行通信和关联?

澄清

赌徒的投资组合和提示者的提示表几乎相同 - 唯一的区别是提示表可以分类(例如赛马、足球等)。

绩效跟踪是关于衡量投资组合/提示表的损益。

【问题讨论】:

  • 我认为这是一个简单的组合与继承问题。您需要组合和至少 3 个有界上下文:提示、赌博、用户目录。性能跟踪将是最后一个的一部分,或者它应该有一个专用的 BC,我不确定,但我只知道一些 DDD...

标签: domain-driven-design bounded-contexts


【解决方案1】:

我确实认为它们是两种不同的背景,你也这么认为,对吧?

我个人会使用赌博环境中的领域事件来生成绩效跟踪信息。代码仍然是松耦合的(因为逻辑只依赖于领域事件)。

您当然可以在它们之间创建不属于任何这些 jars/dll 的适配器。 IE。在 context1 中订阅域事件的东西,调整信息,然后在 context2 中调用东西。这样,您就可以在上下文之间获得 100% 的透明度。

【讨论】:

  • 谢谢。所有响应者都同意这不仅仅是一个 BC - 让我对我的分析更有信心!我倾向于@eulerfx 的答案,但需要多考虑一下。
【解决方案2】:
  1. 如果您看到两个明显独立的模型,只有技术重叠,那么我同意您有两个 BC。但是,请注意,拥有多个 BC,尤其是当它们需要通信时,可能会有点“昂贵”。使用模块要“便宜”得多,这就是为什么你不应该轻易决定拥有多个 BC。

  2. blue book,第 4 部分(战略设计),第 15 章(蒸馏),介绍了非常适合您的场景的通用子域的概念。性能计算可以被视为一个通用子域,因为虽然它们对模型的整体功能至关重要,但它们可以被隔离到一个可供两个 BC 使用的库中。这是一种用于提炼模型并保持技术问题抽象的模式。您无需在 BC 之间实现复杂的消息传递或 RPC 通信,只需使用具有意图揭示接口的共享库即可。

【讨论】:

  • 谢谢。我喜欢这种方法的地方在于它减少了 BC 之间的通信;我最初不喜欢的是共享实现引入了不必要的耦合。但是,仔细考虑一下,引入性能跟踪 BC 的替代方案(赌博 BC 和提示者 BC 使用)也会由于 BC 之间所需的通信量而引入耦合。
  • 刚刚做了一些 DDD 阅读。你所说的通用子域听起来更像是一个共享内核,即性能跟踪确实包含关键域概念。
  • 这里有两个不同的级别。我看到域和子域基本上就像问题空间的分区,而有界上下文存在于解决方案空间中。如果它们匹配是一件好事,但在许多遗留系统中这不会发生。通用子域是域的一部分,它不是特定于域的,因此可能需要第三方解决方案。在您的场景中,用户分析可能是一个潜在的通用子域,您可能依赖于某些框架。
  • @ZioBrando,你的评论让我对这个话题有了一些启示。谢谢。
【解决方案3】:

这显然是(至少)2 个有界上下文 (BC) 的情况,它们具有不同的领域语言这一事实​​是最大的线索。

如果我理解正确,性能跟踪是一个领域概念,它可能应该是 BC 本身。您可以在通用接口类型的项目中定义通用跟踪和特定跟踪(用于提示者)的接口,这些接口将由其他 BC 的实体实现。因此,PerformanceTracking BC 不会关心具体的赌徒或提示者,并且其他 BC 不会耦合到特定的性能跟踪器。

是的,您需要同步 BC,而域事件正是为此目的。这并不完全简单,但如果仔细完成,它不会那么复杂,并且您会从松散耦合的代码中获得巨大的好处。

【讨论】:

  • 谢谢,我没有考虑到性能跟踪可能是它自己的 BC。有趣的。但是,我不确定一旦提取了新的 BC,赌博 BC 中会剩下多少(当然,鉴于描述有限,您无法知道这一点)。我需要再考虑一下,但我怀疑@eulerfx 的建议就足够了。
【解决方案4】:

我可能同意 Mike 的观点,即 Performance Tracking 听起来像是他自己的限界上下文。这看起来像是更明显的边界。

Betters 和 Tipsters 可能作用于相同有界上下文或不同有界上下文的不同聚合。根据您对语言和项目发展的看法,我倾向于选择后者。

【讨论】:

  • 谢谢,我已经对我的问题进行了一些澄清。如果我们假设性能跟踪是一个单独的 BC,那么它是否包含创建投资组合/提示表的概念?如果是这样,赌徒和提示者 BC 应如何通知绩效跟踪 BC 需要创建投资组合/提示表?如果没有,创建逻辑在哪里?在共享内核中?
  • 一个好的观点可能是“谁在乎这个概念”(意味着谁是利益相关者)?据我了解,赌徒和推销员会根据他们的系统部分行事。性能跟踪有不同的目标,因此可能需要不同的模型。
  • BC 之间的耦合应该尽可能低,所以我会继续在它所属的地方创建投资组合:如果赌徒和推销员所做的事情,则应该属于他们的 BC。如果这是在后台发生的事情,它可能会在 Performance Tracking BC 中发生异步通知:“新用户开始赌博!” --> “让我们创建一个投资组合来跟踪他的表现”。我不会在这里使用共享内核。共享内核用于团队之间的明确协作。
  • 赌徒创建自己的投资组合;提示者创建自己的提示表。如果赌徒和提示者都在不同的 BC,那么创建投资组合/提示表的逻辑在哪里(假设它们本质上是相同的)?
  • 好的,问题是“赌徒是否知道他们正在创建投资组合?”如果赌徒知道投资组合,那么它就属于赌博。如果赌徒只是简单地赌博,而投资组合是一个出现在别处的概念,那么它就属于别处。我这里基本申请的是【GRASP信息专家】(en.wikipedia.org/wiki/…)。
猜你喜欢
  • 2015-04-23
  • 2011-05-30
  • 1970-01-01
  • 2011-10-03
  • 2013-11-27
  • 2021-02-23
  • 2021-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多