【架构】-C4模型:把架构图画到合适的层级

架构-C4模型:把架构图画到合适的层级

很多架构图的问题,不是画得不够多,而是把不同层级的东西放在了一起。

用户、外部系统、服务、数据库、业务模块和具体类同时出现在一张图里。读者看完仍然不知道系统边界在哪里,也不知道箭头表示调用、依赖还是数据流。这样的图通常只能由作者自己解释,无法作为团队共同使用的文档。

C4 模型针对的就是这个问题。它把架构拆成四个观察层级,让读者从系统边界一路看到代码结构:

text 复制代码
Context  →  Container  →  Component  →  Code
系统边界    运行单元      业务模块      代码结构

C4 模型由 Simon Brown 提出。它不替你选择单体、微服务或某种数据库,只规定如何把这些设计表达清楚。

四个层级怎么区分

层级 要回答的问题 可以放什么
Context 系统服务谁,依赖谁? 用户、当前系统、外部系统
Container 系统由哪些运行单元组成? 应用、服务、数据库、消息队列
Component 某个运行单元内部如何分工? 控制器、业务服务、适配器
Code 关键模块由什么代码实现? 类、接口、继承和依赖

这里的 Container 不是 Docker 的同义词。一个桌面客户端、一个后端服务或一个数据库,都可以作为 C4 的 Container。

也不必四层全画。大多数项目画清 Context 和 Container 就够了;只有在某个服务复杂到需要专门讨论时,才继续画 Component。Code 图更适合解释一个关键设计,而不是展示整个项目的类目录。

用订单系统举例

Context:先说清楚系统边界

假设要介绍一个订单系统。Context 图只放客户、订单系统以及它依赖的外部系统:

这张图解决两个问题:谁在使用订单系统,订单系统和谁交互。支付平台和仓储系统在边界之外;数据库、接口类和业务模块不应该出现在这里。

Container:再说明系统由什么组成

展开订单系统后,可以看到 Web 前端、订单 API、订单数据库、消息队列和库存服务:

这里需要让读者看懂运行关系。例如,Web 前端通过 HTTP 调用订单 API,订单 API 写入订单数据库并发布消息,库存服务消费消息。只写"API → 队列"是不够的,至少要说明通信方向和用途。

Component 和 Code:复杂处再展开

如果订单 API 已经承担了太多职责,可以把它拆成几个组件:

text 复制代码
订单 API
├── 订单控制器:接收并校验请求
├── 创建订单服务:编排下单流程
├── 库存网关:访问库存服务
├── 支付协调器:处理支付调用
└── 订单仓储:读写订单数据

这时讨论的是模块职责,不是文件夹结构。只有在需要解释接口设计、依赖方向或关键类时,才继续画 Code 图。一个简单服务如果已经能在 Container 图中讲清楚,就应该停在这里。

怎样从零开始绘制

先决定这张图给谁看

读者决定细节:

  • 给产品、管理者或新成员介绍系统,画 Context;
  • 讨论系统拆分和技术依赖,画 Container;
  • 评审某个复杂服务,画 Component;
  • 讨论关键实现,画 Code。

不要试图用一张图满足所有人。一张图只解决一个主要问题,读者才知道应该关注什么。

先写出系统边界

用一句话回答:

这个系统负责什么,不负责什么?

把当前系统放在边界内,把用户、外部系统和基础设施放在边界外。边界没定下来就开始画服务和数据库,最后得到的往往只是依赖清单。

绘制 Context

在中心放当前系统,周围放直接使用它的用户和它主动依赖的外部对象。关系要写业务含义,例如"提交订单""发起支付""同步库存"。这一层不画数据库、类名和内部模块。

拆分 Container

从当前系统内部找出可以独立运行、部署,或承担明确职责的单元:前端、桌面客户端、后端服务、数据库、消息队列、设备适配服务等。

每个 Container 至少写清名称、职责和技术形态:

text 复制代码
名称:订单 API
职责:接收订单请求,协调支付、库存和持久化
技术:HTTP 服务

箭头也要写清楚。相比"订单 API → 支付平台","订单 API 通过 HTTPS 发起支付请求 → 支付平台"能减少很多误解。

按职责划分 Component

Component 不应只是代码目录的另一种画法。按职责拆分,确保每个组件都能用一句话说明自己的工作,并通过明确的接口与其他组件协作。

Code 只画关键部分

Code 图可以展示核心接口、重要依赖和需要评审的类。不要把整个项目的类全部导出;那会变成一张难以维护的代码地图,也无法突出设计重点。

画完后检查

  • 一张图是否只表达一个抽象层级?
  • 每个元素是否写了名称和职责?
  • 每条箭头是否有方向、用途或通信方式?
  • 是否混入了与当前问题无关的细节?
  • 图中的结构是否仍符合当前代码和部署状态?

如果图已经塞不下重点,不要继续缩小字体。把复杂部分拆到下一层,或者改用时序图、部署图或数据模型图。

C4 不负责什么

C4 用来说明"系统由什么组成"。下面这些问题应交给其他图:

  • 时序图:对象如何按时间交互;
  • 部署图:系统运行在哪些节点;
  • ER 图:数据实体如何关联;
  • 流程图:业务步骤如何推进。

把这些内容硬塞进 C4 图,只会让图重新变得难读。

结语

C4 的用处,是让信息出现在合适的层级。先把系统边界和外部关系说清楚,再说明运行单元;只有确实需要时,才深入模块和代码。架构图画到读者已经能做出判断的地方,就该停笔。

相关推荐
长不大的杨瑞杰2 天前
ChatGPT 广告技术栈架构拆解:多轮意图、LLM 工具编排、ANN 召回与拍卖闭环
人工智能·chatgpt·系统架构·推荐系统·广告
艺杯羹3 天前
Windows原生软件锁设计:从暴力杀进程丢数据到零轮询事件驱动架构
windows·系统架构·开源·开源软件·内存管理·开源协议
jktantan3 天前
注解式脱敏:用 Jackson 的 ContextualSerializer 做字段级策略(一)
spring boot·后端·算法·spring cloud·系统架构
艺杯羹5 天前
MCP本地服务集成避坑:从Stdio管道僵死到双向JSON-RPC稳健通信
人工智能·python·ai·系统架构·大语言模型·ai编程·mcp
奇树谦5 天前
Qt Quick 图片加载与 GPU 纹理机制详解:QImage、QQuickTextureFactory、QSGTexture 与异步加载
开发语言·qt·系统架构
无心水6 天前
24、系统架构师论文写作专题 核心考点与学习笔记
笔记·学习·系统架构·架构师·安全架构·软考架构师·软考系统架构设计师
拆房老料7 天前
DeepSeek Super-agent 架构解析:从单任务 Agent 到持续运行的任务系统
人工智能·设计模式·系统架构
Jmyd01237 天前
文物3D数字化的技术选型指南:从WW/T 0115标准到落地工程,一次讲透采集、建档、管理与展示
3d·系统架构·博物馆·数字展厅·博物馆数字化
薛定谔的猫-菜鸟程序员8 天前
软件架构设计师开发资料大全(从入门到精通)
后端·python·系统架构·flask·架构设计师
被放养的研究生8 天前
第一章 信息系统架构
系统架构·金融监管计算机类