用途
该技能用于在领域驱动设计(DDD)中界定和审计模型边界,即限界上下文(Bounded Context)。一句话概括:限界上下文是显式边界,在该边界内,单一模型以及为其命名的通用语言(ubiquitous language)保持一致且完整。
适用场景
- 同一名词在系统不同部位含义不同(例如销售中的“customer”与客服中的“customer”)。
- 模型开始变得纠缠,单个改动会朝意想不到的方向产生连锁反应。
- 团队边界与代码边界不一致。
- 团队正在争论“这是否应该成为独立服务?”。
不适用场景
- 上下文内部的代码重构——应交给战术模式类技能。
- 关于上下文之间如何关联的问题——应交给 ddd-context-mapping。
- 在整个业务范围内分配建模精力——应交给 ddd-subdomain-classification。
核心内容
限界上下文是概念性的,不受部署方式约束。它是模型能够保持自洽的范围。它可以是一个模块、一个包、一个微服务或整个系统——关键在于边界之内,每个术语只有一种含义,每条规则保持一致。
需要划定边界的信号
- 同一个词在系统两个不同部位含义不同。
- 模型的规则会因当前运行的是哪部分代码而相互矛盾。
- 两个团队不断互相干扰对“同一个”模型的修改。
- 某一用户群体的界面与另一群体的界面完全不同,但它们命中的是同一份领域代码。
上下文与微服务
限界上下文是模型边界;微服务是部署边界。二者经常重合,但并非必须如此。单个服务可以承载两个上下文(通过模块边界保持清晰)。两个服务也可以实现同一个上下文(少见,通常是错误做法)。
为边界命名
为每个上下文取一个反映其业务目的的名称:Sales、Billing、Shipping、Identity。避免技术性名称(Backend、Core)。该名称应当让领域专家也能理解。
决策启发式
- 项目初期倾向于更少、更大的上下文。拆分成本低;合并成本高。
- 当术语冲突无法调和、团队需要自治、或模型规则相互矛盾时进行拆分。
- 不要假设一个微服务对应一个限界上下文。映射由模型决定,而非部署拓扑。
反模式
- 为每张数据库表声明一个限界上下文——流于形式,实际上并未划出模型边界。
- 忽视边界直到模型崩坏——到那时清理已成为一个大工程。
- 把“限界上下文”当作“微服务”的同义词。
- 划出边界却没有为边界内的通用语言命名。
参见
- ddd-ubiquitous-language——边界之内承载的内容。
- ddd-context-mapping——上下文之间如何关联。
- ddd-subdomain-classification——哪些上下文值得投入最多精力。
参考资料
Evans, Domain-Driven Design (2003), Ch. 14 (Maintaining Model Integrity).