一个中型电商系统里,“订单”在交易团队意味着”待支付的购物车快照”,在物流团队意味着”等待拣货的配送单”,在财务团队意味着”一条应收账款记录”。三个团队共用同一张
t_order 表、同一个 OrderService
类,每次迭代都互相踩脚。这种混乱的根源不是代码质量,而是缺少一项最基本的架构决策——限界上下文(Bounded
Context) 的划分。
Eric Evans 在 2003 年出版的《领域驱动设计》一书中首次系统化地提出了战略设计(Strategic Design)的概念。二十多年后,这些概念依然是大型系统架构的基石。本文将从限界上下文的本质出发,深入解析上下文映射(Context Mapping)的 9 种模式,并给出可落地的决策框架。
一、限界上下文的本质
1.1 它不是”微服务边界”
在当今的技术社区中,限界上下文常被简单等同于”一个微服务”。这种理解只抓住了表象。Evans 原著中对限界上下文的定义是:
A Bounded Context is a boundary within which a particular model is defined and applicable.
核心要素有三个:
- 模型(Model):一组概念、关系和规则的集合;
- 语言(Ubiquitous Language):团队在该上下文内对概念的统一命名和理解;
- 边界(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 背景
某电商平台在快速发展阶段,系统从单体演进为微服务。初期的服务划分按功能模块拆分(用户服务、商品服务、订单服务……),但随着业务复杂度增长,出现了以下问题:
- “订单服务”承担了交易、支付、物流等多个领域的逻辑;
- 修改价格计算规则需要同时改动促销服务和订单服务;
- 用户服务同时包含了认证、会员、画像三种不同的业务关注点。
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)是战略设计最重要的交付物之一。它用可视化的方式展示系统中所有限界上下文及其关系。
一个完整的上下文地图应该包含:
- 所有已识别的限界上下文;
- 上下文之间的映射关系(用标准化的缩写标注);
- 上下文的负责团队;
- 上下文的核心聚合。
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)等战术模式的设计原则和实践方法。
参考资料
- Evans, Eric. Domain-Driven Design: Tackling Complexity in the Heart of Software. Addison-Wesley, 2003.
- Vernon, Vaughn. Implementing Domain-Driven Design. Addison-Wesley, 2013.
- Brandolini, Alberto. Introducing EventStorming. Leanpub, 2021.
- Skelton, Matthew; Pais, Manuel. Team Topologies. IT Revolution, 2019.
- Context Mapper DSL 官方文档:https://contextmapper.org/
- Conway, Melvin. “How Do Committees Invent?” Datamation, 1968.
- Fowler, Martin. “Bounded Context.” martinfowler.com.
- 张逸.《解构领域驱动设计》. 人民邮电出版社, 2021.
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【系统架构设计百科】复杂性管理:架构的核心战场
系统复杂性是架构腐化的根源——本文从 Brooks 的本质复杂性与偶然复杂性划分出发,结合认知负荷理论与 Parnas 的信息隐藏原则,系统阐述复杂性的来源、度量与控制手段,并给出可操作的架构策略
【系统架构设计百科】DDD 战术模式:聚合、实体与值对象
某团队在实施领域驱动设计时,把整个"订单"建模为一个聚合根(Aggregate Root),其中包含订单基本信息、所有订单行、配送信息、支付记录、物流轨迹、评价数据。结果这个聚合加载一次需要从 7 张表联查,保存一次需要锁定整个订单树。并发下单高峰期,数据库锁等待飙升至秒级。这就是典型的"大聚合"反模式——聚合的边界画…
【系统架构设计百科】防腐层与开放主机服务:系统集成的 DDD 方案
某金融科技公司正在构建新一代交易系统。新系统使用领域驱动设计,模型清晰、代码整洁。然而它必须对接一套运行了 15 年的核心银行系统(Core Banking System)——这套系统的接口返回 COBOL 风格的定长字段,状态码用两位数字表示("01"正常、"02"冻结、"99"未知),金额用"分"而非"元"为单位。…
【系统架构设计百科】DDD 与微服务:用领域模型划分服务边界
某电商团队按数据库表拆分微服务——用户服务管 tuser,商品服务管 tproduct,订单服务管 torder。看起来边界清晰,实际运行中却发现:下单需要同步调用商品服务查价格、调用库存服务检查库存、调用优惠服务算折扣、调用用户服务查地址,一个下单请求扇出 4 次 RPC,任意一个服务超时整条链路就失败。这种"一实体…