DDD第2篇 - 子域与限界上下文

点击上方“xy的技术圈”,选择“设为星标”

认真写文章,用心做分享。

微信公众号:xy的技术圈

个人网站:yasinshaw.com

正文

在上一篇文章中,我们了解了DDD的基本概念以及为什么要使用DDD。

那么具体DDD是如何落地的呢?在前面我们也提到过,DDD是分为“战略模式”和“战术模式”两部分的。项目刚开始的时候,我们可以从业务开始分析,使用战略模式来指导后续开发。

在DDD的战略模式中,有两个很重要的概念,它们分别是“子域”和“限界上下文”。不要被这两个奇怪的名字吓到,其实它们的概念并不复杂。

领域

DDD全称是“领域驱动设计”,那什么是“领域”呢?其实我在上一篇文章也解释过,“领域”指的就是一块业务范围。

具体来讲,每个组织都有它自己的业务范围和做事方式,这个业务范围以及在其中所进行的活动便是领域。如果你为某个组织开发软件时,你面对的就是这个组织的领域。

那我们为什么需要划分子域和限界上下文呢?因为想要试图创建一个全功能的领域模型是非常困难的,并且很容易导致失败。大家都知道,宇宙包含万事万物,但并不是我们每个系统都可以用一个大而全的“宇宙”这样一个模型来承载我们所有的业务行为。

业务范围可能也很大,所以我们需要把这个大的业务范围拆开。如果我们把这个范围看成是一个空间的话,那它同时存在“问题空间”和“解决方案空间”。问题空间是从业务需求方面来看,而解决方案空间是从实现软件方面来看。两者是有一些细微的区别的,最终我们用子域来划分问题空间,用限界上下文来划分解决方案空间

子域

子域是对领域从业务需求方面进行拆分,是逻辑上的。比如一个电商系统,我们可以很明确地可以把它拆分成商品子域、销售子域、仓储子域、客服子域……

子域主要分为三种:

  • 核心子域:业务成功的核心竞争力;

  • 通用子域:不是核心,但被整个业务系统所使用 (可以直接购买的);

  • 支撑子域:不是核心,不被整个系统使用,完成业务的必要能力(可以外包出去的);

我们应该给予核心域最高的优先级,最资深的领域专家和最优秀的开发团队。在实施DDD的过程中,主要关注与核心域。

在划分好了子域以后,可以再回过头来,验证现在划分的子域时候已经解决了全部问题空间的问题。如果没有,则可以再进行适当调整。

限界上下文

通用语言

要理解限界上下文,首先要了解什么是通用语言。事实上实施DDD战略模式的时候,最重要的一点便是统一语言。我们知道,每个人对一个事物的理解可能都是有一些微小的差别的。比如在谈到“商品”的时候,在“店铺”这个业务场景可能比较关注的是商品的标题、图片、价格等等,但在库存这个业务场景,关注的可能是商品的编号、存量、入库时间和出库时间等等。

所以同一个词可能要不同的意思。尤其是一些比较宽泛的词,如“商品”、“订单”、“用户”等等。这样就可能会造成歧义,我说的模型和你说的模型可能不是同一个模型。如果不加以区分,最终设计出来的模型可能就是一个过于复杂和混乱的模型。

所以我们需要统一语言,比如在销售上下文中,商品叫做“销售商品”,在库存上下文中,叫做“库存货物”,在物流上下文中,叫做“物流货物”等等。

这样便可以在不同的业务场景关注不同的属性,有不同的操作,从而设计出更能准确表达业务意义的模型。

限界上下文是一个边界,领域模型便存在在这个边界之内。当模型被一个显示的边界所包围时,其中每个概念的含义便是确定的了。因此,限界上下文主要是一个语义上的边界

限界上下文的划分原则

原则上,一个上下文就对应一个子域。但这并不是绝对的,限界上下文的目的是为了更加明确领域模型的职责和范围,是从“解决方案空间”来考虑问题的。通常来说,一个限界上下文可以是一个微服务,或者一个Module。

那么如何划分限界上下文呢?具体来讲,有三个原则可以参考:

  • 概念相同,含义不同:即上面所说的“通用语言”的例子,如果一个模型在一个上下文里面有歧义,那有歧义的地方就是边界所在,应该把它们拆到不同的限界上下文中。

  • 外部系统:有时候系统需要同外部系统打交道,这个时候可以把与外部系统打交道的那部分拆分出去以实现更好的扩展性。这样一旦外部系统发生了变化,就不会影响到我们的核心业务逻辑。

  • 像组织扩展:尽量不要两个团队一起在一个限界上下文里面开发,因为这样可能会存在沟通不顺畅、集成困难等问题。

DDD第2篇 - 子域与限界上下文_第1张图片

上下文映射

当我们划分好了限界上下文后,就需要考虑一下上下文的映射关系了。为什么要考虑它们之间的映射关系呢?因为这样可以让我们从宏观上看到每个上下文之间的关系,从而能够更好地指导我们后续的程序设计。另一方面,如果一旦发现某个限界上下文与过多的其它限界上下文具有联系,那可能需要考虑拆分这个限界上下文了。

我们用Upstream的首字母U来标识“上游”,用Downstream的首字母D来标识“下游”。那怎么去判断“上游”还是“下游”呢?这里有一个原则:下游的模型依赖于上游的模型和服务

我们对上面的图进行限界上下文的映射之后可以得到:

DDD第2篇 - 子域与限界上下文_第2张图片

通过上述的过程,便可以把模型隔离开来,形成一个个限界上下文。这样具体在开发过程中,一个限界上下文就可以对应一个微服务或者module。限界上下文之间一般使用“事件”来进行信息交互,如此便可以实现低耦合。

敬请期待

《DDD第3篇 - 事件风暴》

END

DDD第2篇 - 子域与限界上下文_第3张图片

推荐阅读

  • DDD第1篇 - 为什么使用DDD?

↓↓↓ 点击"阅读原文" 去【评论】吧

你可能感兴趣的:(DDD第2篇 - 子域与限界上下文)