跳转到内容

限界上下文(Bounded Context)

用途:划分系统边界、判断某个模型该归谁、决定服务拆分依据时查阅

限界上下文是一个显式的语义与职责边界:在该边界内,某个领域模型是自洽有效的,术语有唯一含义;边界之间不共享模型,只能通过明确定义的映射关系协作。

它同时划定了三样东西:模型的适用范围、统一语言的作用域、谁有权变更这套语义。

当系统规模变大,一个“大而全”的模型必然退化:同一个词在不同部门含义不同,不同部分的规则相互冲突,任何一处修改都可能牵动全局。早期做法是把所有概念塞进一个统一模型(或一个共享数据库),结果是模型内部充满条件分支与例外。

Evans 的主张是反过来:不追求全局一致的模型,而是承认语义有边界,在每个边界内保持严格一致,边界之间用显式转换衔接。这是 DDD 中“战略设计”的核心工具。

出现以下任一信号,说明可能应该切开:

信号 说明
同名词含义分歧 同一个词在两处的定义、生命周期或规则不同(“账户”在记账侧与客户侧)
规则相互矛盾 两边都想生效且互斥
变更原因不同 一边因监管变化,一边因运营策略变化
一致性要求不同 一边要求强一致,一边可接受延迟一致
数据所有权不清 双方都在写同一张表
团队与发布节奏不同 一起发布成为长期摩擦点

反向信号(说明边界划错):两个上下文之间长期存在同步调用与字段级耦合;一次业务变更必须同时改两边才能生效。

常被混为一谈 区别
微服务 服务是部署与运行时边界,上下文是语义边界。数量一致是巧合,不是目标
代码模块 模块常与上下文对齐,但一个上下文可以是单体内的一个包
数据库 schema 上下文不应通过共享表实现集成,共享持久化结构等于共享模型
团队组织 组织边界影响上下文边界(康威定律),但语义边界应由业务决定,不能反向迁就
子域 子域属于问题空间(业务如何分解),上下文属于解空间(模型如何组织);两者通常不是一对一
模式 含义 耦合度 使用时机
遵奉模型(Conformist) 下游直接采用上游模型 高 上游是外部标准或不可控
共享内核(Shared Kernel) 两方共用一小块模型并一起演进 高 确实同源且能同步发布,范围必须极小
客户-供应商(Customer-Supplier) 上游按下游需求排期 中 同一组织内两个团队
防腐层(Anti-Corruption Layer) 下游用适配器隔离并转换上游模型 低 对接外部系统、遗留系统、第三方平台
开放主机服务 + 发布语言(OHS/PL) 上游以明确协议对外提供服务 低 公共能力被多方消费

工程上最常被低估的是防腐层:外部系统的模型一旦直接进入核心域,后续所有业务规则都会被外部字段结构绑架,替换成本迅速升高。

  1. 包级模块化(推荐起点):在单体内按上下文建包,每个上下文对外只暴露接口层,禁止跨上下文直接访问对方仓储与表;用依赖规则或架构测试(如 ArchUnit 类断言)在构建期固化。
  2. 契约层显式化:跨上下文交互通过 DTO / 事件 Schema(发布语言)表达,禁止传递领域对象。
  3. 上下文地图(Context Map):一张标注了上下文与其映射关系的图,作为架构资产随代码版本维护,而不是画一次就过期的 PPT。
  4. 独立部署:仅当团队节奏、扩容、故障隔离或技术栈差异明确要求时才拆分;语义边界稳定是拆分的必要条件,不是充分条件。
概念 关系
统一语言 上下文是语言的作用域,语言是上下文的判据
聚合 聚合是上下文内部的模型单元,跨聚合引用不出上下文
防腐层 边界处的转换实现,是上下文隔离的技术手段
集成模式 上下文边界常成为服务/模块的集成边界与数据一致性边界

适用:多团队协作的中大型业务系统;存在遗留系统或外部系统需要长期共存;同一概念在不同部门语义分歧明显。

低收益:单人小系统、纯数据管道、以 CRUD 为主的内部工具。强行划分只会增加间接层。

  • 上下文即服务:为拆而拆,形成同步调用链,模型仍未改善。
  • 共享大内核:公共模块不断膨胀,最终所有上下文互相牵制。
  • 外部模型直入:第三方字段结构成为内部实体,替换供应商时全量返工。
  • 只有图没有约束:上下文地图存在,但代码里跨边界访问无人拦截。
  • Eric Evans《领域驱动设计》第 14、15 章(限界上下文与上下文映射)
  • Vaughn Vernon《实现领域驱动设计》第 2 章
  • Martin Fowler bliki 词条 Bounded Context
  • Sam Newman《Building Microservices》(服务边界的运维与组织视角,与语义视角互补)