3. 通用语言与限界上下文:如何建立团队通用语言,限界上下文的定义与识别,上下文映射图
领域驱动设计(DDD)的核心在于将复杂的业务逻辑转化为可执行的软件模型。而实现这一转化的桥梁,正是通用语言(Ubiquitous Language)与限界上下文(Bounded Context)。本章将深入探讨如何建立团队通用语言,定义与识别限界上下文,并通过上下文映射图(Context Map)来管理它们之间的关系。
3.1 通用语言:团队沟通的基石
通用语言是领域专家与开发团队共享的一套语言,它贯穿于所有讨论、文档、代码和测试中。没有通用语言,团队将陷入“翻译”的泥潭,导致需求误解、模型混乱和代码腐化。
3.1.1 通用语言的构成要素
| 要素 | 说明 | 示例(电商领域) |
|---|---|---|
| 术语 | 业务概念的唯一名称 | “订单”、“商品”、“库存”、“支付单” |
| 规则 | 术语之间的约束与行为 | “订单提交后,必须锁定库存” |
| 关系 | 术语之间的关联方式 | “一个订单包含多个订单项” |
| 场景 | 术语与规则在特定流程中的体现 | “用户下单 -> 创建订单 -> 扣减库存 -> 生成支付单” |
3.1.2 建立通用语言的步骤
- 事件风暴(Event Storming):组织领域专家与开发团队共同参与的工作坊,通过贴纸在白板上梳理业务事件、命令、聚合和策略。
- 术语表(Glossary):将事件风暴中产生的关键术语整理成团队共享的术语表,明确每个术语的定义、同义词和反义词。
- 代码映射:将术语表中的概念直接映射到代码中的类名、方法名和模块名,确保代码即文档。
- 持续精炼:在迭代过程中,通过代码评审、需求澄清和回顾会议,不断修正和丰富通用语言。
实践提示: 通用语言不是一成不变的。当发现同一个术语在不同场景下含义不同时,这往往是识别限界上下文边界的重要信号。
3.2 限界上下文:模型的边界
限界上下文是DDD中最重要的战略设计模式。它定义了模型应用的边界,在边界内部,通用语言是统一且自洽的;在边界外部,模型可能以不同的方式被理解或使用。
3.2.1 限界上下文的定义
一个限界上下文是一个显式的边界,领域模型在这个边界内部是自洽的。它通常对应一个独立的子系统、微服务或模块。每个限界上下文都有自己的通用语言、领域模型和数据库模式。
3.2.2 识别限界上下文的方法
- 按业务能力:识别核心业务能力,如“订单管理”、“支付处理”、“物流配送”,每个能力通常对应一个限界上下文。
- 按语言变化:当同一个术语在不同团队或不同业务场景中含义发生变化时,就是限界上下文的边界。例如,“客户”在销售上下文指“潜在客户”,在售后上下文指“已购客户”。
- 按团队结构:康威定律指出,系统架构会反映组织沟通结构。一个独立的团队通常负责一个或多个限界上下文。
- 按数据所有权:每个限界上下文拥有自己的数据存储,避免跨上下文直接访问数据库。
常见误区: 不要将限界上下文与微服务划等号。一个限界上下文可以拆分为多个微服务,但一个微服务不应跨越多个限界上下文。
3.3 上下文映射图:连接限界上下文
上下文映射图(Context Map)是描述限界上下文之间关系的战略设计工具。它帮助团队理解系统全局,并指导集成策略的选择。
3.3.1 上下文映射图的核心关系
| 关系类型 | 描述 | 集成策略 |
|---|---|---|
| 合作关系(Partnership) | 两个上下文需要协同工作,共同完成一个业务目标 | 紧密协作,共享事件或API |
| 共享内核(Shared Kernel) | 两个上下文共享一部分模型和代码 | 共享库或公共模块 |
| 客户-供应商(Customer-Supplier) | 上游上下文(供应商)为下游上下文(客户)提供数据或服务 | 上游提供API,下游消费 |
| 防腐层(Anti-Corruption Layer) | 下游上下文通过一个转换层隔离上游上下文的模型变化 | 适配器模式、门面模式 |
| 开放主机服务(Open Host Service) | 上下文对外提供一组明确的API,供其他上下文调用 | RESTful API、gRPC |
| 发布语言(Published Language) | 上下文使用一种标准的数据格式或协议进行通信 | JSON Schema、Avro、Protobuf |
| 分离方式(Separate Ways) | 两个上下文之间没有直接依赖关系 | 通过消息队列或事件总线异步通信 |
3.3.2 上下文映射图示例
以下是一个电商系统的上下文映射图,展示了核心限界上下文及其关系。
3.4 从通用语言到上下文映射图:实践案例
假设一个电商团队在事件风暴中发现了“订单”和“支付”两个核心概念。起初,团队将“订单”和“支付”放在同一个模型中,但很快发现“支付”涉及第三方网关、退款、对账等复杂逻辑,且“支付”的“订单”概念与“订单管理”的“订单”概念在生命周期和状态上存在差异。
通过识别语言变化(“订单”在支付上下文中更关注“支付金额”和“支付状态”),团队决定将“支付”拆分为独立的限界上下文。随后,他们绘制了上下文映射图,明确了“订单上下文”作为客户,“支付上下文”作为供应商,通过防腐层隔离支付网关的变化。
关键收获: 通用语言是发现限界上下文边界的雷达,而上下文映射图是管理这些边界之间关系的蓝图。两者结合,为API设计提供了清晰的战略指导。