Domain, Subdomain, and Bounded Context
1. What is domain
上一篇文章讲了DDD的设计初衷, 组成部分, 路线图, 但始终没有解释什么是domain. Domain在字典中翻译为: 感兴趣的领域, 或人们能够控制的领域. 这么说可能还是有些模糊, 以下图为例, 如何为以下图像分类:
不同的人面对上图可能有不同的想法, 有些人根据形状分类, 有些人通过颜色分类, 还有一些人根据其他方式分类:
上图中第一组根据Shape(形状)分类, 因此是Shape Domain, 因为其关注点为Shape; 第二组根据Color(颜色)分类, 因此是Color Domain; 因此, Domain就是工作所面对的问题和解法.
2. Problem Space and Solution Space
对于真实业务, 每个组织都有自己的独特的业务范围与解决方式, 而工作中遇到的问题和解法就是domain的组成. 在传统开发流程中, 会将问题与解法分离, 业务团队负责提出问题和规格, 开发团队负责解决和维护. 以下是两者之间可能存在的映射关系:
随着业务逻辑复杂度不断提升, 在缺乏交流和规范的情况下, 业务团队与开发团队的沟通成本不断加重. 一旦业务团队没有表达清楚需求, 或是缺乏从整体的角度去思考问题, 则产品很容易出问题. 而面对突然冒出的需求, 开发者通常只能利用当前架构修修补补, 且很难应对未来需求的变化. DDD的做法则不同, 它将问题和解法结合在一起, 以下是一个简单的例子:
可以看到, 项目中含有三个domain, 分别具有自己的Problem Space和Solution Space. 这也需要业务团队与开发团队更多的沟通, 让开发人员对于需求有更深刻的了解.
3. Subdomain
定义完domain后, 开发者可能想创建一个domain model来实现domain的所有功能. 但实际上, domain的problem space还可以继续分解, 称为subdomain(子域). Subdomain根据优先级, 功能性, 替代性分为以下三种类型:
- Core Doamin(核心域): 整个domain中最重要的, 也是最耗时开发的, 例如: 商品推荐需求
- Supporting Subdomain(支持域): 支援core domain的附属功能, 且没有现成方案可以套用, 例如: 购物需求
- Generic subdomain(通用域): core domain和supporting subdomain都用到的功能, 也可以包含外部依赖, 例如: 身份认证需求
三种subdomain的关系可类比为下图:
总结一下, subdomain可以当做某个domain中的domain, subdomain拥有和domain相同的定义. 但请注意, 我们一直没有提到solution space. 所有的subdomain都是围绕着拆解problem space而展开. Subdomain自身也可以被继续拆分成多个subdomain, 形成多层嵌套的domain:
4. Bounded Context
Bounded Context为Solution Space的Domain Model建立一个语意边界, 让domain mode在数据和行为上都能符合Ubiquitous Language和业务需求. 其定义可以解释为: 一个可以让单词或句子获得完整意义的环境. 举个例子, 当我们形容国家首脑时, 需要考虑"国家"这个上下文: 对于美国是"总统", 对于英国是"首相", 对于德国是"总理". 一个solution space包含一个或多个BC.
对于软件开发来说, 当开发者根据不断迭代的需求往系统中添加功能时, 每个需求其实都有自己的BC, 同一名词在不同的BC下存在不同的定义. 以下图为例, Account在Bank BC下是关于资产管理, 在Social BC中是关于好友管理, 在Blog BC下是关于文章管理. 如果Account被三个系统共用, 每个系统的开发者都将面对一个巨大且杂乱的Account.
因此每个BC都应有自己的一套Ubiquitous Language, 这样就不会在开发Blog Account时需要考虑Social Account的资料, 也不用担心影响到Bank Account.
5. Difference Between Subdomain and Bounded Context
Subdomain是对业务需求的拆分与分类; Bounded Context是对解决方案的拆解和分类. 两者紧密相连也很容易搞混, 就像是地板和地毯的关系. Subdomain是地板, Bounded Context是地毯. 当你装修完时, 需要保证地板和地毯完全匹配; 当某天需要换地毯时, 会发现新地毯无法百分之百匹配, 甚至会被家具(Legacy System)挡住, 这时两者的差异才会显现出来.
6. E-Commerce Example
以电商为例, 电商可能的需求如下:
- Product Catalog: 商品目录
- Order: 订单
- Payment: 支付
- Shipping: 物流
- Invoice: 发票
- Inventory: 仓库
- Forecast: 推荐
在使用Strategic Design前, 项目规划可能如下:
上图中, 虚线表示subdomain的边界, 实线表示系统的边界. 这其中有几点问题:
- E-Commerce system承担了太多责任
- 没有业务重点被划出来
- 难以修改或新增其他功能
在应用Strategic Design时, 需要先为subdomain分类:
- Core domain: Optimal Acquisition(优化购物体验需求, 如推荐系统)
- Supporting domain: Purchasing(购物需求)
- Supporting Subdomain: Inventory(仓储需求)
- Generic Subdomain: Resource Planning(其他资源管理请求)
以此作为Bounded Context的边界, 新的软件架构如下: