领域驱动设计——领域、子域、限界上下文

3,306 阅读4分钟

概述

领域

广义上讲,领域是一个组织所做的事情以及其中包含的一切。

即‘领域’指的是一块业务范围。

一个系统的业务范围可能很大, 很难创建一个大而全的模型,所以需要将整个业务范围进行拆分。

如果这个范围被看成是一个空间的话,那它同时存在‘问题空间’和‘解决方案空间’。问题空间是从业务需求方面来看,而解决方案空间是从实现软件方面来看。两者的实现有一些微小差别, 最终我们用子域划分问题空间(问题空间包括核心域和多个子域),用限界上下文划分解决方案空间(解决方案空间包括多个限界上下文)。

子域

子域是对领域从业务需求层面进行拆分, 是逻辑上的。比如一个电商系统,可以拆成商品子域、订单子域、仓储子域、物流子域...

子域划分

  • 核心子域:业务最有价值的部分,系统成功的关键。
  • 通用子域:非核心,但是整个业务系统都会用到
  • 支撑子域:非核心,用于支撑部分子域,完成业务的必要能力。

所以我们需要在核心域上面投入更多,配置最好的团队。

限界上下文

在设计一个系统时,通常会有一些用于团队内部交流的术语、词组、句子,这在DDD中叫作通用语言。

对于同样的术语,在不同的上下文环境可能会有不同的语义。如‘盘点’一般指对设备进行盘点,但在某些上下文下也可表示对人进行盘点。所以对于一个术语只有在指定限界上下文后才有明确的含义。

限界上下文是一个边界,领域模型便存在这个边界之内。当模型被一个显示的边界包围时,其中的每个概念便都是确定的。

划分原则

一般而言,一个上下文对应一个子域。

实现

限界上下文可以实现为一个单独的项目,部署成微服务应用;也可以实现成一个模块。

示例

from 实现领域驱动设计

上下文的映射图

为什么需要上下文映射图

通过绘制上下文映射图,我们可以清晰的项目之间的依赖关系,这往往决定系统是否成功。

上下文映射图的绘制

在上下文映射图中,有上游下游的概念,下游的模型依赖于上游的模型和服务。比如日程上下文就依赖于用户上下文,所以日程上下文是下游,而用户上下文是上游。

上下文的绘制通常按照下面模版填充即可

from 实现领域驱动设计

上下文之间的关系

合作关系:两个限界上下文,要么都成功,要么都失败。

共享内核:两个限界上下文之间模型和代码共享,依赖会比较紧密。

客户方-供应方:上下游关系, 上游的供应方需要顾及到下游的客户方。

遵奉者:上下游关系, 但是上游不一定可靠,作出的承诺无法保证能够兑现。

防腐层(ACL):我们往往需要将上游的模型翻译成下游的模型。 如果两个限界上下文之间模型翻译比较复杂,下游就需要创建一个单独的防腐层,该层负责与上游系统通信,并负责模型之间的翻译转换。

开发主机服务(OHS):定义一种协议,客户端可以通过该协议调用你的服务。

发布语言(PL):一种发布出来的语言用于集成上下文之间交流。

开放主机+发布语言简单的理解就是:系统通过http、tcp或者其他协议暴露服务(开放主机),资源的描述可以是xml、json或者其他(发布语言)。

示例

from 实现领域驱动设计

系统自治性

我们知道在具有上下游关系的两个系统中,下游的可用性依赖于上游。如果上游系统宕机,下游系统部分功能也不可用,这样的系统便不具有自治性。

如果把下游依赖的模型存储到本地,通过消息或者Rest请求定时更新本地模型,这样即使上游系统不用,本地系统依然可以正常工作,这样的系统便有更多的自治性。