上下文图(Context Diagram)是系统设计中最顶层的一张图。它只回答三个问题:系统是什么、谁在用它、它跟哪些外部系统有交互。不展示任何内部实现,只画边界。正因为简单,它往往是架构沟通中信息密度最高、受众最广的一张图。
一、上下文图是什么
上下文图,又称系统上下文图或 Level 0 数据流图,是结构化系统分析的起点。
它的核心特征:
| 特征 | 说明 |
|---|---|
| 单一中心 | 整个系统只画一个方框/圆圈,不拆分内部组件 |
| 只画边界 | 图上只有"系统内部"和"系统外部"两个区域 |
| 外部实体 | 围绕中心的所有人、系统、组织都是外部实体 |
| 数据流 | 箭头标注系统与外部实体之间传递的数据/请求 |
| 零实现细节 | 不画数据库、不画微服务、不画代码结构 |
一张上下文图,就是系统的一张"身份证"——告诉所有人这个系统的范围在哪、跟谁打交道、打交道的方式是什么。
二、上下文图的三类元素
| 元素类型 | 图形约定 | 含义 | 示例 |
|---|---|---|---|
| 系统 | 中心方框或圆圈 | 你要建设/维护的软件系统 | "在线支付平台"、"教务管理系统" |
| 外部人员 | 矩形(方框) | 直接使用系统的真人角色 | "用户"、"管理员"、"运营人员" |
| 外部系统 | 矩形(方框) | 与系统交互但不在你控制范围内的其他系统 | "支付网关"、"短信服务"、"CRM" |
注意区分:运维工程师不是外部人员,除非他直接使用系统界面。如果只是维护系统的人,不画在图上。上下文图画的是直接交互方,不是所有利益相关者。
三、上下文图与相邻图表的关系
很多人会把上下文图和架构图、DFD搞混。它们的关系是层层递进的关系:
| 图表类型 | 视角 | 粒度 | 内部结构 | 典型用途 |
|---|---|---|---|---|
| 上下文图 | 系统边界 | 最粗,系统=1个方框 | 无 | 范围界定、需求确认、干系人沟通 |
| 数据流图(DFD Level 1) | 内部数据流 | 中等,系统拆为几个主要过程 | 有子过程 | 需求分析、流程梳理 |
| 架构图 | 技术实现 | 最细,展示组件/服务/数据库 | 完整技术栈 | 技术方案评审、开发参考 |
| 用例图 | 功能视角 | 用例级别 | 角色与功能映射 | 需求验证、功能范围 |
一句话总结:上下文图画的是"系统的外墙",DFD画的是"墙内的走廊",架构图画的是"每间房里的家具"。
四、C4模型中的上下文图
在 C4 架构描述模型中,上下文图对应 Level 1(System Context),是四个层级中的最顶层:
| C4层级 | 名称 | 内容 | 对应角色 |
|---|---|---|---|
| Level 1 | System Context | 系统作为一个整体 + 外部交互 | 所有人(含非技术干系人) |
| Level 2 | Container | 系统内部的主要容器(应用、数据库、消息队列等) | 架构师、技术负责人 |
| Level 3 | Component | 每个容器内部的组件/模块 | 开发工程师 |
| Level 4 | Code | 类级别细节(可选,很少画) | 具体开发者 |
C4模型强调:Level 1 上下文图是"所有架构沟通的起点"。不是代码、不是架构图,而是这张最简单的边界图。因为只有先回答"系统是什么、谁在用、跟谁连",才能讨论内部怎么实现。
五、六步绘制法
第1步:定义系统
给系统起一个清晰的名字。用干系人能理解的业务名称,不用技术名称。
- 正确示例:"订单交易系统"、"在线支付平台"
- 错误示例:"Spring Boot微服务集群 v2.3"、"Java后端"
写一句话描述系统的核心职责:这个系统做什么?它在什么场景下提供什么价值?
第2步:识别外部人员
问自己四个问题:
- 谁直接使用这个系统?(列出所有角色)
- 每个角色用系统做什么?(动作级别)
- 有没有来自合作方的外部用户?(如合作商户)
- 有没有内部团队通过系统界面操作的人?
注意:只画直接交互的人。不画间接干系人(如CEO不直接用系统,不画)。
第3步:识别外部系统
问自己三个问题:
- 系统需要调用哪些外部服务?(出站调用)
- 哪些外部系统会调用本系统?(入站调用)
- 有没有内部遗留系统被当作"黑盒"对待?
原则:如果某个系统不在你团队的修改范围内,就画成外部系统。不因为它是公司内部的就不画。
第4步:绘制数据流
用带标签的箭头连接系统和外部实体。每条箭头标注三个要素:
| 要素 | 说明 | 示例 |
|---|---|---|
| 方向 | 谁发起的数据传输 | 用户→系统:提交订单 |
| 内容 | 传输的是什么数据 | 系统→支付网关:支付请求 |
| 双向 | 如果是双向交互,用双向箭头 | 用户↔系统:登录认证 |
标签用动词+名词格式,如"提交订单"、"查询库存"、"推送状态通知"。避免模糊标签如"数据交互"、"通信"。
第5步:审查边界
画完后,逐项自检:
- 系统边界是否清晰?一个方框代表整个系统?
- 外部实体数量是否合理?建议3-8个,超过8个考虑是否画得太细
- 每个外部实体是否直接与系统交互?有没有画了不该画的间接干系人?
- 箭头标签是否具体?能不能一眼看懂在传什么数据?
- 非技术人员能否看懂这张图?拿给产品经理看一遍
第6步:迭代更新
上下文图不是画完就锁死。以下场景需要更新:
- 新增外部系统集成时(如接入新的支付渠道)
- 系统边界发生变化时(如拆分微服务、合并系统)
- 新增用户角色时(如开放给合作伙伴使用)
- 架构评审或需求评审时定期复核
六、五个常见错误
错误1:把内部组件画进来了
上下文图只画一个系统方框。数据库、缓存、消息队列、微服务——这些是内部实现,不属于上下文图的范畴。画进来就成了架构图,失去了上下文图"最简沟通"的价值。
错误2:外部实体太多
如果图上有15个外部实体,说明你在画需求清单而不是系统边界。聚焦核心交互方,3-8个最佳。次要的可以合并或省略。
错误3:标签太模糊
箭头上写"数据交互"、"API调用"——等于没写。标签要具体到"提交订单请求"、"返回支付结果"这种动作+对象的粒度。
错误4:混入实现技术
系统方框上写"K8s集群"、"Redis缓存"——上下文图不关心技术栈。一个方框只写业务名称和核心职责。技术细节留给架构图。
错误5:忘记验证
画完直接归档,不拿给干系人看。上下文图最大的价值是"对齐认知"——你以为系统边界是这样的,产品以为边界是那样的,运营以为边界又不一样。不验证,就白画了。
七、与其他图表的配合
上下文图不是孤立使用的,它是图表体系的入口:
| 配合图表 | 配合方式 | 价值 |
|---|---|---|
| 架构图 | 上下文图定义边界 → 架构图展示边界内的技术实现 | 先对齐范围再讨论实现 |
| 数据流图(DFD) | 上下文图定义Level 0 → DFD Level 1拆分内部过程 | 从粗到细的层次化分析 |
| 时序图 | 上下文图标注的数据流 → 时序图展示具体调用时序 | 从数据流到调用细节 |
| ER图 | 上下文图标注的系统 → ER图展示系统内部数据模型 | 从系统范围到数据结构 |
| 用例图 | 上下文图的外部人员 → 用例图的角色来源 | 从角色识别到功能映射 |
八、工具选择
| 工具 | 适用场景 | 优点 | 不足 |
|---|---|---|---|
| 纸笔/白板 | 快速讨论、头脑风暴 | 零门槛、随时修改、参与感强 | 无法保存和版本管理 |
| draw.io / Excalidraw | 正式文档、评审材料 | 免费、上手快、导出格式多 | 无结构化校验 |
| Lucidchart | 企业协作、多人编辑 | 模板丰富、协作流畅 | 付费 |
| Structurizr | C4模型专用 | 直接生成C4四层图、语义化 | 学习门槛较高 |
上下文图结构极简,任何工具都能画。选工具的关键不在于功能多少,而在于"干系人能不能打开看"。如果评审人打不开文件,画得再好也没用。
九、自检清单
发布前逐项核对:
- 系统方框只有一个?名称用的是业务语言?
- 外部实体数量在3-8个之间?每个都有明确交互?
- 每条数据流箭头都有具体标签(动词+名词)?
- 图上没有任何内部组件、数据库、技术栈信息?
- 拿给非技术人员看过?他能看懂系统范围?
- 系统边界与需求文档中的范围一致?
- 所有外部系统的交互方向是否标注清楚?
- 是否记录了制图日期和版本号?
- 是否标注了假设和约束条件?
