惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Hacker News: Front Page
博客园 - 【当耐特】
量子位
博客园 - 聂微东
H
Hackread – Cybersecurity News, Data Breaches, AI and More
The Register - Security
The Register - Security
Last Week in AI
Last Week in AI
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tailwind CSS Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
雷峰网
雷峰网
Blog — PlanetScale
Blog — PlanetScale
P
Proofpoint News Feed
Jina AI
Jina AI
The Cloudflare Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
AWS News Blog
AWS News Blog
L
LINUX DO - 最新话题
酷 壳 – CoolShell
酷 壳 – CoolShell
The GitHub Blog
The GitHub Blog
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
Security @ Cisco Blogs
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Schneier on Security
Stack Overflow Blog
Stack Overflow Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Engineering at Meta
Engineering at Meta
W
WeLiveSecurity
博客园 - 三生石上(FineUI控件)
Security Archives - TechRepublic
Security Archives - TechRepublic
Hugging Face - Blog
Hugging Face - Blog
T
Troy Hunt's Blog
C
CERT Recently Published Vulnerability Notes
N
News and Events Feed by Topic
S
SegmentFault 最新的问题
美团技术团队
C
CXSECURITY Database RSS Feed - CXSecurity.com
人人都是产品经理
人人都是产品经理
SecWiki News
SecWiki News
N
News and Events Feed by Topic
C
Check Point Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
宝玉的分享
宝玉的分享
Schneier on Security
Schneier on Security
阮一峰的网络日志
阮一峰的网络日志
Cisco Talos Blog
Cisco Talos Blog
T
Threat Research - Cisco Blogs
J
Java Code Geeks

土法炼钢兴趣小组的算法知识备份

国密算法与国密 TLS 系列索引 【系统架构设计】架构质量属性:不只是"高可用高性能" 【系统架构设计百科】告警策略:如何避免"狼来了" 【系统架构设计】CQRS:读写分离的架构哲学 【系统架构设计】空间架构:极端扩展场景的解法 【系统架构设计】微服务架构深度审视:优势、代价与适用边界 【系统架构设计】扩展性原理:水平、垂直与对角扩展 【系统架构设计】无状态设计:扩展的第一步也是最难的一步 【系统架构设计】缓存架构:从本地到分布式的多级缓存体系 【系统架构设计】管道与过滤器:Unix 哲学的架构表达 【系统架构设计】复杂性管理:架构的核心战场 【系统架构设计】消息队列架构:异步解耦的设计与陷阱 【系统架构设计】CDN 架构:全球加速的设计原理 【系统架构设计】连接池设计:被忽视的性能杀手 【系统架构设计】弹性设计模式:熔断器、舱壁与超时 【系统架构设计】高可用设计模式:冗余、故障转移与仲裁 【系统架构设计】容量规划:从拍脑袋到数据驱动 【系统架构设计】数据库扩展:分库分表的工程实践与替代方案 【系统架构设计】SLO 工程:可靠性的量化管理 【系统架构设计】性能建模:用数学思维分析系统瓶颈 【系统架构设计】混沌工程:主动验证系统的韧性 【系统架构设计】零拷贝与内存映射:数据搬运的极致优化 【系统架构设计】线程模型:从 thread-per-request 到协程 【系统架构设计】容灾架构:多活与灾备设计 【系统架构设计】数据库性能模式:索引、查询与连接管理 【系统架构设计】数据建模:从关系范式到文档模型的真实权衡 【系统架构设计】吞吐量优化:批处理、流水线与并发模型 【系统架构设计】流处理架构:从批处理到实时的范式迁移 【系统架构设计】搜索引擎架构:倒排索引之上的系统设计 【系统架构设计】时序数据架构:监控与 IoT 的存储设计 【系统架构设计】数据迁移与版本化:在线不停机的数据演进 【系统架构设计】数据湖与数据仓库:分析架构的演进路线 【系统架构设计】API 网关设计:入口层的职责边界 【系统架构设计】应用层数据一致性模式:在正确性与性能之间走钢丝 【系统架构设计】多模数据库选型:Polyglot Persistence 的工程实践 【系统架构设计】服务发现与注册:动态拓扑的基础设施 【系统架构设计】配置管理架构:从配置文件到配置中心 【系统架构设计】全链路压测:大规模系统的性能验证 【系统架构设计】幂等性设计:分布式环境下的安全重试 【系统架构设计】契约测试与 Schema 演进:服务间的信任协议 【系统架构设计】长连接与推送架构:WebSocket、SSE 与 MQTT 【系统架构设计】延迟分析:从 P50 到 P999 的全链路追踪 【系统架构设计百科】DDD 战术模式:聚合、实体与值对象 【系统架构设计百科】防腐层与开放主机服务:系统集成的 DDD 方案 【系统架构设计百科】领域事件与事件风暴:从业务到架构的桥梁 【系统架构设计百科】CQRS + Event Sourcing 完整实战:从领域建模到部署 【系统架构设计百科】DDD 与微服务:用领域模型划分服务边界 【系统架构设计百科】认证架构:从 Session 到 JWT 到 OIDC 【系统架构设计】API 设计哲学:REST vs GraphQL vs gRPC 的真实权衡 排序算法专题:从 TimSort 到并行排序 【密码学百科】国密算法体系:SM2/SM3/SM4/SM9 全景解读 【密码学百科】承诺方案:Pedersen 承诺、向量承诺与多项式承诺 【密码学百科】不经意传输与隐私信息检索:OT、OT 扩展与 PIR 【密码学百科】门限密码学:门限签名、门限解密与分布式密钥生成 完美哈希:从理论到 gperf 实践 【密码学百科】安全多方计算:从 Yao 的混淆电路到实用 MPC 【密码学百科】同态加密:从 Paillier 到全同态加密(FHE) 【密码学百科】零知识证明系统:zk-SNARKs、zk-STARKs 与 Bulletproofs 【密码学百科】概率论与密码分析:生日攻击、差分分析与线性分析 【密码学百科】计算复杂性与归约:密码安全性证明的基石 【密码学百科】秘密共享:Shamir 方案、VSS 与安全多方计算入口 【密码学百科】椭圆曲线代数:Weierstrass 方程、点群运算与曲线选择 【密码学百科】离散对数与配对密码学:从 DLP 到 BLS 签名 【密码学百科】格密码数学基础:SVP、LWE 与格基约化 【密码学百科】抽象代数:群、环、域的密码学视角 【密码学百科】有限域算术:GF(2^n) 运算与在 AES/ECC 中的应用 【密码学百科】数论进阶:二次剩余、椭圆曲线上的 Weil 配对 【密码学百科】密码学简史:从凯撒密码到量子时代 【密码学百科】威胁模型与安全目标:CIA 三要素之外 【密码学百科】Kerckhoffs 原则与现代密码设计哲学 【密码学百科】随机性:密码学的基石 【密码学百科】信息论入门:熵、完美保密与 Shannon 定理 【密码学百科】分组密码原理:Feistel 网络与 SPN 结构 【密码学百科】AES 逐步拆解:SubBytes 到 MixColumns 的数学 【密码学百科】分组密码工作模式全览:ECB/CBC/CTR/OFB/CFB 【密码学百科】流密码:RC4 的兴衰与 ChaCha20 的崛起 【密码学百科】密码学哈希函数:MD5→SHA-2→SHA-3 的进化之路 【密码学百科】MAC 与 HMAC:消息认证的正确姿势 【密码学百科】认证加密(AEAD):GCM、ChaCha20-Poly1305 与 OCB 【密码学百科】密钥派生函数:HKDF、PBKDF2、Argon2 与密码存储 【密码学百科】公钥密码的数论基础:模运算、群、原根 【密码学百科】RSA 从原理到攻击:教科书 RSA 为什么不安全 【密码学百科】Diffie-Hellman 密钥交换与离散对数问题 【密码学百科】椭圆曲线密码学(ECC):从几何直觉到点群运算 【密码学百科】数字签名:ECDSA、EdDSA 与 Schnorr 签名 【密码学百科】现代密钥交换:X25519、ECDHE 与前向保密 【密码学百科】混合加密与 KEM/DEM 范式:ECIES 与 HPKE 【密码学百科】填充方案:PKCS#1 v1.5、OAEP 与 PSS 【密码学百科】TLS 协议全解析:从握手到 0-RTT 【密码学百科】PKI 与数字证书:信任链的构建与崩塌 【密码学百科】密码认证协议:从 SRP 到 OPAQUE 【密码学百科】零知识证明入门:如何证明你知道而不泄露 【密码学百科】安全信道构造:Noise 协议框架与 Signal 协议 【密码学百科】密钥管理工程:HSM、KMS 与密钥生命周期 【密码学百科】侧信道攻击:从时序攻击到功耗分析 【密码学百科】密码学实现陷阱:三层漏洞分类、审计工具链与系统性预防 密码敏捷性:如何设计可升级的密码系统 【密码学百科】OpenSSL/BoringSSL 架构剖析:ENGINE、Provider 与 FIPS 模块 【Linux 网络子系统深度拆解】内核网络调优方法论:从基准测试到生产验证 排序基准测试:用数据说话
【系统架构设计】DDD 战略设计:限界上下文与上下文映射
2026-04-13 · via 土法炼钢兴趣小组的算法知识备份

一个中型电商系统里,“订单”在交易团队意味着”待支付的购物车快照”,在物流团队意味着”等待拣货的配送单”,在财务团队意味着”一条应收账款记录”。三个团队共用同一张 t_order 表、同一个 OrderService 类,每次迭代都互相踩脚。这种混乱的根源不是代码质量,而是缺少一项最基本的架构决策——限界上下文(Bounded Context) 的划分。

Eric Evans 在 2003 年出版的《领域驱动设计》一书中首次系统化地提出了战略设计(Strategic Design)的概念。二十多年后,这些概念依然是大型系统架构的基石。本文将从限界上下文的本质出发,深入解析上下文映射(Context Mapping)的 9 种模式,并给出可落地的决策框架。

上一篇:推送架构 | 下一篇:DDD 战术模式


一、限界上下文的本质

1.1 它不是”微服务边界”

在当今的技术社区中,限界上下文常被简单等同于”一个微服务”。这种理解只抓住了表象。Evans 原著中对限界上下文的定义是:

A Bounded Context is a boundary within which a particular model is defined and applicable.

核心要素有三个:

  1. 模型(Model):一组概念、关系和规则的集合;
  2. 语言(Ubiquitous Language):团队在该上下文内对概念的统一命名和理解;
  3. 边界(Boundary):模型和语言的适用范围。

限界上下文首先是一个语义边界,而不是一个部署单元。一个限界上下文可以对应一个微服务,也可以对应一个单体中的模块,甚至可以对应一个第三方系统。

1.2 通用语言:上下文的灵魂

通用语言(Ubiquitous Language)是限界上下文的核心驱动力。在同一个上下文内,所有人——开发者、产品经理、领域专家——必须使用完全相同的术语来描述同一个概念。

上下文:交易域
  "订单" = 用户提交的一次购买意图,包含商品快照、价格、优惠信息
  "下单" = 创建订单的行为
  "取消" = 用户主动放弃未支付订单

上下文:物流域
  "订单" = 一条等待拣货和配送的指令
  "下单" = 物流系统接收到配送请求
  "取消" = 配送中止,触发退货流程

同一个词”订单”在不同上下文中有不同含义,这不是问题——这正是限界上下文存在的意义。问题在于把两种含义混在同一个模型里。

1.3 上下文边界的识别信号

以下信号通常意味着你需要拆分上下文:

信号 说明
同一术语在不同团队有不同含义 “订单”在交易和物流中语义不同
一个实体承担过多职责 User 类同时包含认证、画像、社交属性
修改一个功能需要协调多个团队 改价格逻辑需要交易和促销团队同时参与
数据模型中出现大量可选字段 不同场景只用到部分字段
业务规则互相矛盾 交易域要求”订单不可修改”,客服域要求”订单可修改”

二、Evans 的核心概念重新解读

2.1 领域与子域

在 Evans 的体系中,领域(Domain)是整个业务问题空间,子域(Subdomain)是其自然划分。子域有三种类型:

┌──────────────────────────────────────────────┐
│                  业务领域                      │
│                                              │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐   │
│  │ 核心子域  │  │ 支撑子域  │  │ 通用子域  │   │
│  │ Core     │  │Supporting│  │ Generic  │   │
│  │          │  │          │  │          │   │
│  │ 竞争优势  │  │ 必要但非  │  │ 标准化   │   │
│  │ 需要深度  │  │ 核心差异  │  │ 可外购   │   │
│  │ 领域建模  │  │ 化能力   │  │ 或复用   │   │
│  └──────────┘  └──────────┘  └──────────┘   │
└──────────────────────────────────────────────┘
  • 核心子域(Core Subdomain):企业的竞争优势所在,值得投入最好的团队和最深的建模;
  • 支撑子域(Supporting Subdomain):业务必需但不构成差异化竞争力;
  • 通用子域(Generic Subdomain):认证、通知、日志等标准化能力。

2.2 子域与限界上下文的关系

子域是问题空间的划分,限界上下文是解决方案空间的划分。二者的关系不是简单的一对一:

关系 场景
一个子域 → 一个上下文 理想情况
一个子域 → 多个上下文 子域复杂度高,需要进一步拆分
多个子域 → 一个上下文 遗留系统,子域边界模糊

2.3 限界上下文的内部结构

一个限界上下文内部通常包含:

┌─────────────────────────────────────┐
│        限界上下文(Bounded Context)  │
│                                     │
│  ┌───────────┐  ┌───────────┐      │
│  │ 领域层     │  │ 应用层    │       │
│  │ - 聚合    │  │ - 应用服务 │      │
│  │ - 实体    │  │ - 命令处理 │      │
│  │ - 值对象  │  │ - 查询处理 │      │
│  │ - 领域服务│  │           │       │
│  │ - 领域事件│  │           │       │
│  └───────────┘  └───────────┘      │
│                                     │
│  ┌───────────┐  ┌───────────┐      │
│  │ 基础设施层 │  │ 接口层    │       │
│  │ - 仓储实现│  │ - API     │      │
│  │ - 消息发布│  │ - 事件消费 │      │
│  │ - 持久化  │  │ - 转换器  │       │
│  └───────────┘  └───────────┘      │
└─────────────────────────────────────┘

三、上下文映射的 9 种模式

上下文映射(Context Mapping)描述的是两个限界上下文之间的关系。这种关系既包含技术层面的集成方式,也包含组织层面的团队协作模式。

3.1 全景图

graph TB
    subgraph "上下文映射模式"
        SK["共享内核<br/>Shared Kernel"]
        CS["客户-供应商<br/>Customer-Supplier"]
        CF["遵从者<br/>Conformist"]
        ACL["防腐层<br/>Anti-Corruption Layer"]
        OHS["开放主机服务<br/>Open Host Service"]
        PL["发布语言<br/>Published Language"]
        PT["合作关系<br/>Partnership"]
        SW["各行其道<br/>Separate Ways"]
        BBM["大泥球<br/>Big Ball of Mud"]
    end

    subgraph "按团队协作分类"
        direction TB
        M1["互利对等"] --> PT
        M1 --> SK
        M2["上下游依赖"] --> CS
        M2 --> CF
        M2 --> ACL
        M3["公共接口"] --> OHS
        M3 --> PL
        M4["无协作"] --> SW
        M4 --> BBM
    end

3.2 共享内核(Shared Kernel)

两个上下文共享一小部分模型(代码、数据库 schema 或消息格式)。

  • 适用场景:两个密切协作的团队需要共享核心领域概念;
  • 组织前提:团队之间信任度高,修改共享部分需要双方同意;
  • 风险:共享部分越大,耦合越深;任何修改都可能影响两个上下文。
// shared-kernel 模块:两个上下文都依赖
package com.example.shared.kernel;

public class Money {
    private final BigDecimal amount;
    private final Currency currency;

    public Money(BigDecimal amount, Currency currency) {
        if (amount == null || currency == null) {
            throw new IllegalArgumentException("金额和币种不能为空");
        }
        this.amount = amount;
        this.currency = currency;
    }

    public Money add(Money other) {
        if (!this.currency.equals(other.currency)) {
            throw new IllegalArgumentException("币种不一致,无法直接相加");
        }
        return new Money(this.amount.add(other.amount), this.currency);
    }

    // equals 和 hashCode 基于值比较
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Money)) return false;
        Money money = (Money) o;
        return amount.compareTo(money.amount) == 0
            && currency.equals(money.currency);
    }
}

3.3 客户-供应商(Customer-Supplier)

上游上下文是供应商,下游上下文是客户。下游的需求会影响上游的优先级。

  • 适用场景:两个团队有明确的上下游关系,下游能影响上游的路线图;
  • 组织前提:上游团队愿意倾听下游需求并调整接口;
  • 典型例子:订单上下文(上游)为物流上下文(下游)提供订单数据。
上游(订单)                    下游(物流)
┌───────────┐   需求反馈   ┌───────────┐
│ OrderService│ ←────────── │ ShippingService│
│           │   提供 API   │           │
│           │ ──────────→  │           │
└───────────┘              └───────────┘

3.4 遵从者(Conformist)

下游上下文完全接受上游的模型,不做任何转换。

  • 适用场景:上游是强势的第三方系统或组织标准,下游没有谈判余地;
  • 组织前提:下游团队接受上游模型对自身领域模型的”入侵”;
  • 风险:下游的领域模型被上游污染,业务语义可能被扭曲。

3.5 防腐层(Anti-Corruption Layer)

下游在自己与上游之间建立一个翻译层,将上游模型转换为自己的领域模型。

  • 适用场景:需要对接遗留系统或外部系统,但不希望被其模型污染;
  • 组织前提:下游有能力和意愿投入资源建设翻译层;
  • 实现方式:Facade + Adapter + Translator 三层结构。
// 防腐层示例:将遗留 ERP 的订单模型转换为本域模型
type ERPOrder struct {
    OrdNo     string  `json:"ord_no"`
    CustCode  string  `json:"cust_code"`
    TotalAmt  float64 `json:"total_amt"`
    StatusFlg int     `json:"status_flg"`
}

type DomainOrder struct {
    OrderID    OrderID
    CustomerID CustomerID
    Total      Money
    Status     OrderStatus
}

// Translator:负责模型转换
func translateERPOrder(erp ERPOrder) (DomainOrder, error) {
    status, err := mapERPStatus(erp.StatusFlg)
    if err != nil {
        return DomainOrder{}, fmt.Errorf("未知的 ERP 状态码: %d", erp.StatusFlg)
    }
    return DomainOrder{
        OrderID:    NewOrderID(erp.OrdNo),
        CustomerID: NewCustomerID(erp.CustCode),
        Total:      NewMoney(erp.TotalAmt, CNY),
        Status:     status,
    }, nil
}

详细实现请参见 防腐层与开放主机服务

3.6 开放主机服务(Open Host Service)

上游定义一组公开协议(API),供多个下游使用。

  • 适用场景:上游需要服务多个不同的下游上下文;
  • 组织前提:上游有专门的接口设计和版本管理能力;
  • 典型形式:RESTful API、gRPC 服务、GraphQL 端点。
              ┌───────────────┐
              │ Open Host     │
              │ Service       │
              │ (标准化 API)   │
              └───────┬───────┘
                      │
          ┌───────────┼───────────┐
          │           │           │
    ┌─────┴─────┐┌────┴────┐┌────┴────┐
    │ 下游 A    ││ 下游 B  ││ 下游 C  │
    └───────────┘└─────────┘└─────────┘

3.7 发布语言(Published Language)

上下文之间通过一种公共的、文档化的数据交换格式进行通信。

  • 适用场景:需要在多个上下文之间交换领域数据,且格式需要标准化;
  • 常见形式:JSON Schema、Protocol Buffers、Avro Schema、XML Schema;
  • 关系:通常与 Open Host Service 配合使用。
// published_language/order_events.proto
syntax = "proto3";
package order.events;

message OrderCreatedEvent {
    string order_id = 1;
    string customer_id = 2;
    repeated LineItem items = 3;
    MoneyValue total = 4;
    google.protobuf.Timestamp created_at = 5;
}

message LineItem {
    string product_id = 1;
    int32 quantity = 2;
    MoneyValue unit_price = 3;
}

message MoneyValue {
    string amount = 1; // 使用字符串避免浮点精度问题
    string currency = 2;
}

3.8 合作关系(Partnership)

两个上下文的团队建立一种对等的合作关系,共同规划和协调开发。

  • 适用场景:两个上下文高度相关,必须同步演进;
  • 组织前提:团队之间有对等的话语权,愿意共同承担协调成本;
  • 风险:协调成本随团队规模增长迅速上升。

3.9 各行其道(Separate Ways)

两个上下文之间没有任何集成关系,各自独立发展。

  • 适用场景:集成成本高于收益,或业务上确实不需要交互;
  • 注意:这是一个主动的设计决策,不是忽视集成需求。

3.10 大泥球(Big Ball of Mud)

这不是一种推荐的模式,而是对现实的描述——系统中没有清晰的上下文边界,各种概念混杂在一起。

  • 识别信号:修改任何一个功能都可能影响看似无关的部分;
  • 应对策略:在大泥球的外围建立防腐层,逐步剥离新的上下文。

四、上下文映射模式的决策树

面对两个需要集成的上下文,如何选择合适的映射模式?以下决策树提供了一个系统化的判断路径:

flowchart TD
    START["两个上下文需要集成"] --> Q1{"两个团队能否<br/>紧密协作?"}
    Q1 -->|是| Q2{"需要共享<br/>部分模型?"}
    Q1 -->|否| Q3{"下游能否影响<br/>上游的接口?"}

    Q2 -->|是| SK["共享内核<br/>Shared Kernel"]
    Q2 -->|否| PT["合作关系<br/>Partnership"]

    Q3 -->|是| CS["客户-供应商<br/>Customer-Supplier"]
    Q3 -->|否| Q4{"上游模型是否<br/>可以接受?"}

    Q4 -->|是| CF["遵从者<br/>Conformist"]
    Q4 -->|否| Q5{"集成是否<br/>值得投入?"}

    Q5 -->|是| ACL["防腐层<br/>ACL"]
    Q5 -->|否| SW["各行其道<br/>Separate Ways"]

    CS --> Q6{"上游需要服务<br/>多个下游?"}
    Q6 -->|是| OHS["开放主机服务<br/>+ 发布语言"]
    Q6 -->|否| CS2["保持客户-供应商"]

4.1 Shared Kernel vs ACL 的关键决策因素

这两种模式是最容易混淆的,以下对比帮助做出判断:

维度 Shared Kernel Anti-Corruption Layer
团队信任度 高,愿意共同维护 低或不可控
模型一致性 共享部分的模型完全一致 两侧模型可以完全独立
变更协调成本 每次修改需双方同意 各自独立修改
耦合度 高(共享代码/schema) 低(通过翻译层隔离)
适用团队规模 小团队(2-3 个上下文) 任意规模
实现成本 低(直接复用) 高(需要建设翻译层)
维护成本 高(协调成本) 中(翻译层维护)
典型场景 同一产品线的核心概念 对接遗留系统或外部服务

4.2 选择建议的总结表

模式 适用的组织关系 适用的技术场景 主要风险
Shared Kernel 紧密协作的小团队 核心概念确实相同 耦合扩散
Partnership 对等协作的团队 需要同步演进的上下文 协调成本高
Customer-Supplier 上下游关系明确 下游有合理需求 上游优先级冲突
Conformist 下游无谈判余地 上游模型基本可接受 模型污染
ACL 下游需要保护模型 对接遗留/外部系统 翻译层维护成本
OHS + PL 一对多服务 提供标准化接口 版本管理复杂度
Separate Ways 无协作关系 集成价值低于成本 数据不一致
Big Ball of Mud 遗留系统 无边界的混沌系统 所有风险

五、上下文边界与团队边界的对齐

5.1 康威定律的启示

梅尔文·康威(Melvin Conway)在 1968 年提出的康威定律(Conway’s Law)指出:

设计系统的组织,其产出的系统架构必然是该组织沟通结构的映射。

这意味着限界上下文的边界最终会趋向于团队的边界。反过来,如果你的架构边界与团队边界不一致,两者之间必然产生摩擦。

5.2 反向康威策略

反向康威策略(Inverse Conway Maneuver)是指主动调整组织结构来匹配目标架构。如果你希望系统由三个限界上下文组成,那就组建三个团队,每个团队负责一个上下文。

目标架构:
┌──────────┐  ┌──────────┐  ┌──────────┐
│ 交易上下文 │  │ 物流上下文 │  │ 支付上下文 │
└──────────┘  └──────────┘  └──────────┘

组织结构(对齐后):
┌──────────┐  ┌──────────┐  ┌──────────┐
│ 交易团队  │  │ 物流团队  │  │ 支付团队  │
│ 5-8 人   │  │ 5-8 人   │  │ 3-5 人   │
└──────────┘  └──────────┘  └──────────┘

5.3 Team Topologies 的四种团队类型

Matthew Skelton 和 Manuel Pais 在《Team Topologies》一书中定义了四种基础团队类型,与限界上下文的分类可以形成映射:

团队类型 说明 对应的子域类型
流对齐团队(Stream-aligned) 面向业务价值流交付 核心子域
使能团队(Enabling) 帮助其他团队克服技术障碍 跨多个子域
复杂子系统团队(Complicated-subsystem) 负责需要深度专业知识的组件 技术复杂的支撑子域
平台团队(Platform) 提供底层基础设施能力 通用子域

5.4 一个团队应该负责多少个上下文?

核心原则是认知负载(Cognitive Load)——一个团队能有效理解和维护的领域复杂度是有限的。

经验法则: - 一个 5-8 人的团队通常负责 1-2 个限界上下文; - 如果一个团队负责 3 个以上的上下文,说明上下文粒度可能太细,或团队需要拆分; - 如果一个上下文需要 15 人以上的团队,说明上下文粒度可能太粗。


六、工程案例:电商系统的上下文映射

6.1 背景

某电商平台在快速发展阶段,系统从单体演进为微服务。初期的服务划分按功能模块拆分(用户服务、商品服务、订单服务……),但随着业务复杂度增长,出现了以下问题:

  1. “订单服务”承担了交易、支付、物流等多个领域的逻辑;
  2. 修改价格计算规则需要同时改动促销服务和订单服务;
  3. 用户服务同时包含了认证、会员、画像三种不同的业务关注点。

6.2 重新建模

团队采用事件风暴(参见 领域事件与事件风暴)重新梳理业务领域,识别出以下限界上下文:

graph LR
    subgraph "核心子域"
        TC["交易上下文<br/>Trading Context"]
        PC["定价上下文<br/>Pricing Context"]
    end

    subgraph "支撑子域"
        SC["物流上下文<br/>Shipping Context"]
        PAY["支付上下文<br/>Payment Context"]
        INV["库存上下文<br/>Inventory Context"]
    end

    subgraph "通用子域"
        AUTH["认证上下文<br/>Auth Context"]
        NOTIFY["通知上下文<br/>Notification Context"]
    end

    TC -->|"Customer-Supplier"| SC
    TC -->|"Partnership"| PC
    TC -->|"Customer-Supplier"| PAY
    TC -->|"Customer-Supplier"| INV
    TC -->|"OHS + PL"| NOTIFY
    AUTH -->|"OHS + PL"| TC
    AUTH -->|"OHS + PL"| SC

6.3 上下文映射决策

上游 下游 映射模式 决策理由
交易 物流 Customer-Supplier 物流需求明确,交易团队愿意配合
交易 定价 Partnership 两者紧耦合,需要同步演进
交易 支付 Customer-Supplier 支付需求标准化程度高
认证 全部 OHS + PL 认证提供标准化 JWT 接口
交易 通知 OHS + PL 通知是通用能力
交易 遗留 ERP ACL ERP 模型老旧,不允许修改

6.4 效果

重新划分后,团队对齐到各自的限界上下文:

  • 交易团队和定价团队由于 Partnership 关系,采用同一个 Sprint 节奏;
  • 物流团队作为 Customer 可以向交易团队提出接口需求;
  • 认证团队维护 OHS,提供标准化的 JWT 发放和验证 API;
  • 对接遗留 ERP 系统时,交易团队通过 ACL 保护了自己的领域模型。

交付效率在三个月内提升约 40%,跨团队沟通冲突减少约 60%。


七、上下文映射的可视化工具

7.1 上下文地图

上下文地图(Context Map)是战略设计最重要的交付物之一。它用可视化的方式展示系统中所有限界上下文及其关系。

一个完整的上下文地图应该包含:

  1. 所有已识别的限界上下文;
  2. 上下文之间的映射关系(用标准化的缩写标注);
  3. 上下文的负责团队;
  4. 上下文的核心聚合。

7.2 标准缩写

缩写 模式
SK Shared Kernel
CS / U-D Customer-Supplier / Upstream-Downstream
CF Conformist
ACL Anti-Corruption Layer
OHS Open Host Service
PL Published Language
PT Partnership
SW Separate Ways
BBM Big Ball of Mud

7.3 工具推荐

工具 特点 适用阶段
白板 + 便利贴 最灵活,适合初期探索 事件风暴工作坊
Miro / FigJam 远程协作友好 远程事件风暴
Context Mapper DSL 代码化的上下文地图 设计文档化
PlantUML / Mermaid 文本化绘图 技术文档
Structurizr C4 模型集成 架构决策记录

八、战略设计的常见误区

8.1 误区一:限界上下文等于微服务

限界上下文是逻辑边界,微服务是物理边界。一个限界上下文可以是一个单体中的模块,一个微服务中的包,甚至可以跨越多个部署单元。先划上下文,再决定部署策略。

8.2 误区二:先定技术架构再识别上下文

正确的顺序是:理解业务 → 识别子域 → 划分限界上下文 → 选择映射模式 → 决定部署架构。技术架构应该服务于业务架构,而不是相反。

8.3 误区三:上下文边界一旦确定就不变

限界上下文是演进式的。随着业务发展和团队对领域理解的深入,上下文边界应该持续调整。常见的演进模式包括:

  • 拆分:一个上下文变得过大,拆分为两个;
  • 合并:两个上下文的边界模糊,合并为一个;
  • 重新定义:发现更合理的边界。

8.4 误区四:追求”完美”的上下文划分

不存在唯一正确的划分方案。两个不同的团队面对同一个业务,可能画出不同但都合理的上下文边界。关键不在于”正确”,而在于一致性和可演进性

8.5 误区五:忽视组织因素

纯技术视角的上下文划分注定失败。一个上下文如果跨越三个不同部门的职责范围,那它在组织现实中很难作为一个整体运作。


九、实施战略设计的步骤

9.1 第一步:识别核心子域

与领域专家一起,明确哪些是企业的核心竞争力。这些子域值得最深入的建模和最好的团队资源。

9.2 第二步:绘制现状上下文地图

描述系统当前的上下文关系,包括那些不理想的 Big Ball of Mud。诚实面对现状是改进的前提。

9.3 第三步:设计目标上下文地图

基于业务发展方向和组织规划,设计目标状态的上下文地图。

9.4 第四步:制定演进路径

从现状到目标不是一步到位的。需要制定分阶段的演进计划,每个阶段都应该能独立交付业务价值。

阶段 1:在大泥球外围建立 ACL,隔离核心域
阶段 2:从大泥球中剥离第一个限界上下文
阶段 3:建立 OHS,为新上下文提供标准接口
阶段 4:逐步迁移剩余功能到独立上下文

9.5 第五步:持续验证和调整

每个 Sprint 或迭代周期结束后,回顾上下文边界是否仍然合理,映射模式是否需要调整。


十、战略设计的综合权衡

决策维度 细粒度上下文 粗粒度上下文
团队自治 高:每个团队独立决策 低:需要内部协调
模型纯净度 高:每个上下文语义清晰 低:可能混合多种语义
集成复杂度 高:上下文间交互多 低:内部调用
数据一致性 难:需要跨上下文最终一致 易:事务边界内强一致
部署独立性 高:各自独立部署 低:需要协调部署
认知负载 低:每个上下文容易理解 高:需要理解多个概念
运维成本 高:更多的服务和基础设施 低:更少的运维对象
性能 可能受跨服务调用影响 内部调用效率高
适合阶段 成熟业务、大团队 创业期、小团队

十一、从战略到战术

战略设计回答的是”系统应该分成哪几块”的问题,而战术设计回答的是”每一块内部应该怎么组织”的问题。战略设计的输出——限界上下文和上下文映射——是战术设计的输入。

在下一篇文章中,我们将深入限界上下文的内部,探讨聚合(Aggregate)、实体(Entity)、值对象(Value Object)等战术模式的设计原则和实践方法。

下一篇:DDD 战术模式:聚合、实体与值对象


参考资料

  1. Evans, Eric. Domain-Driven Design: Tackling Complexity in the Heart of Software. Addison-Wesley, 2003.
  2. Vernon, Vaughn. Implementing Domain-Driven Design. Addison-Wesley, 2013.
  3. Brandolini, Alberto. Introducing EventStorming. Leanpub, 2021.
  4. Skelton, Matthew; Pais, Manuel. Team Topologies. IT Revolution, 2019.
  5. Context Mapper DSL 官方文档:https://contextmapper.org/
  6. Conway, Melvin. “How Do Committees Invent?” Datamation, 1968.
  7. Fowler, Martin. “Bounded Context.” martinfowler.com.
  8. 张逸.《解构领域驱动设计》. 人民邮电出版社, 2021.

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-13 · architecture

【系统架构设计】复杂性管理:架构的核心战场

系统复杂性是架构腐化的根源——本文从 Brooks 的本质复杂性与偶然复杂性划分出发,结合认知负荷理论与 Parnas 的信息隐藏原则,系统阐述复杂性的来源、度量与控制手段,并给出可操作的架构策略

2026-04-13 · architecture

【系统架构设计】DDD 战术模式:聚合、实体与值对象

某团队在实施领域驱动设计时,把整个"订单"建模为一个聚合根(Aggregate Root),其中包含订单基本信息、所有订单行、配送信息、支付记录、物流轨迹、评价数据。结果这个聚合加载一次需要从 7 张表联查,保存一次需要锁定整个订单树。并发下单高峰期,数据库锁等待飙升至秒级。这就是典型的"大聚合"反模式——聚合的边界画…

2026-04-13 · architecture

【系统架构设计】防腐层与开放主机服务:系统集成的 DDD 方案

某金融科技公司正在构建新一代交易系统。新系统使用领域驱动设计,模型清晰、代码整洁。然而它必须对接一套运行了 15 年的核心银行系统(Core Banking System)——这套系统的接口返回 COBOL 风格的定长字段,状态码用两位数字表示("01"正常、"02"冻结、"99"未知),金额用"分"而非"元"为单位。…

2026-04-13 · architecture

【系统架构设计】DDD 与微服务:用领域模型划分服务边界

某电商团队按数据库表拆分微服务——用户服务管 tuser,商品服务管 tproduct,订单服务管 torder。看起来边界清晰,实际运行中却发现:下单需要同步调用商品服务查价格、调用库存服务检查库存、调用优惠服务算折扣、调用用户服务查地址,一个下单请求扇出 4 次 RPC,任意一个服务超时整条链路就失败。这种"一实体…