1. 从一张草图到一套系统:diagram-design 到底在解决什么问题
第一次看到“diagram-design”这个标题,很多人会以为它只是教你怎么画图——选个模板、拖几个框、连几条线,导出 PNG 就完事了。但真正在项目里画过架构图、流程图、时序图的人都知道,画图本身只占整个工作量的两成,剩下八成的时间全花在“对齐”上:对齐团队对系统边界的理解、对齐不同角色对流程节点的认知、对齐文档和代码之间的映射关系。diagram-design 要解决的,恰恰是这八成的问题。
我把它定义为一套“以图为核心的表达系统”。它不只是画图工具的组合,而是一整套从信息梳理、结构抽象、视觉编码到协作维护的方法论。你手里可能已经有 Draw.io、Excalidraw、Figma、Mermaid 这些工具,但工具本身不会告诉你:什么时候该用泳道图而不是流程图,什么时候该把一张大图拆成三张小图,什么时候该用颜色编码而不是加文字注释。这些决策才是 diagram-design 的核心价值。
这套东西适合谁?如果你是后端开发,需要给团队讲清楚一次请求经过了哪些服务、哪些中间件、哪些存储层,那 diagram-design 能帮你把“口头描述十分钟”压缩成“一张图三十秒看懂”。如果你是产品经理,需要在需求评审会上让业务方、开发、测试三方对同一个流程达成一致,那 diagram-design 能帮你提前暴露歧义点。如果你是技术写作者,需要维护一套长期更新的文档系统,那 diagram-design 能帮你建立图与文之间的同步机制,避免“图改了文档没改”的经典事故。
我见过太多项目在早期用一张随手画的草图推进,到了中期图已经和代码完全脱节,新人进来只能靠读代码反推架构。diagram-design 的思路是:把图当作一等公民来维护,给它版本、给它评审、给它和代码一样的更新节奏。下面我会从设计思路、核心细节、实操过程、常见问题四个维度,把这套方法拆开讲透。
2. 整体设计思路:为什么是“先抽象后视觉”,而不是“先画图后补逻辑”
2.1 图的本质是信息压缩,不是美术创作
很多人画图的第一反应是打开工具、拖一个矩形、写个名字、再拖一个箭头。这个顺序是反的。diagram-design 的第一原则是:先确定这张图要回答什么问题,再决定用什么图形元素。一张图如果试图同时回答“系统有哪些模块”“模块之间怎么调用”“调用时传了什么参数”“异常怎么处理”,那它一定会变成一团乱麻。
我的做法是先把信息分层。以一次典型的接口调用为例,我会问自己四个问题:第一,参与者有谁(用户、网关、服务、数据库)?第二,它们之间的交互顺序是什么?第三,每一步的输入输出是什么?第四,哪些步骤可能失败、失败后怎么补偿?这四个问题对应四种图:上下文图、时序图、数据流图、状态图。如果强行用一张图回答四个问题,读者需要在大脑里做四次解码,认知负担极高。
提示:一张图只回答一个问题。如果发现一张图里出现了两种以上的连线语义(比如实线表示调用、虚线表示数据流、点划线表示依赖),那说明这张图该拆了。
2.2 视觉编码要遵循“预注意处理”原则
人眼在看到一个图形时,前 200 毫秒是无意识处理的,这个阶段叫预注意处理。颜色、大小、形状、位置这些属性会被自动识别,而文字标签需要主动阅读才能理解。diagram-design 的核心技巧就是:把最重要的信息放在预注意通道里,把次要信息放在文字标签里。
举个例子,如果你要表达“这个服务是核心服务,那个是边缘服务”,不要写“核心服务”四个字,而是把核心服务的矩形加粗、放大、用深色填充。读者一眼就能看出主次,不需要逐个读标签。再比如,如果你要表达“这条链路是主链路,那条是降级链路”,不要用文字标注“主”“降级”,而是用实线和虚线区分。实线默认是主路径,虚线默认是备选路径,这是大多数读者的直觉认知。
我见过一个反例:某项目的架构图里,所有服务都用同一种蓝色矩形,然后靠文字标签区分“网关”“服务”“存储”。读者需要逐个读标签才能理解结构。后来我把网关改成圆角矩形、服务改成直角矩形、存储改成圆柱体,读者扫一眼就能识别出三类角色。这就是预注意处理的力量。
2.3 工具选型:不是越强大越好,而是越“可维护”越好
diagram-design 不绑定特定工具,但选型时有三个硬指标:第一,是否支持文本化定义(这样图可以进版本控制);第二,是否支持自动布局(这样改一个节点不需要手动挪十个箭头);第三,是否支持导出多种格式(这样同一张图可以同时用于文档、演示、代码注释)。
基于这三个指标,我的推荐组合是:Mermaid 用于流程和时序类图(文本定义、版本友好),Excalidraw 用于需要手绘风格的草图(快速、低门槛),Draw.io 用于需要精确布局的架构图(网格对齐、导出稳定)。Figma 适合做视觉稿,但不适合做技术图,因为它的强项是像素级控制,而技术图需要的是结构级控制。
注意:不要在一个项目里混用超过两种画图工具。工具越多,维护成本越高,图与图之间的风格越难统一。我见过一个项目同时用了 Mermaid、Draw.io、ProcessOn、Visio 四种工具,最后没人知道哪张图是最新的。
3. 核心细节解析:从信息梳理到视觉落地的五个关键环节
3.1 信息梳理:用“名词-动词”法提取图的基本元素
拿到一个需求或一段代码,不要急着画框。先做一件事:把所有名词圈出来,把所有动词圈出来。名词就是潜在的节点,动词就是潜在的连线。比如“用户提交订单,订单服务校验库存,库存服务返回结果,订单服务写入数据库”,这里的名词是用户、订单、库存、数据库,动词是提交、校验、返回、写入。节点和连线的雏形就有了。
但这一步有个坑:不是所有名词都值得成为节点。如果某个名词只出现一次、且没有交互,它可能只是一个属性,不需要单独画框。比如“订单金额”只是一个字段,不需要画成节点。判断标准是:这个名词是否与其他节点有交互?如果有,就是节点;如果没有,就是属性。
3.2 结构抽象:确定图的层级和边界
一张图应该画到多细?这是最常被问到的问题。我的经验法则是:如果一张图超过 15 个节点,读者就会开始迷失。超过 20 个节点,读者基本放弃理解。所以当节点数超过 15 时,就要考虑分层。
分层的做法是:先画一张高层图,只包含 5 到 7 个核心模块,每个模块用一个矩形表示。然后为每个模块单独画一张细化图,展开内部的 5 到 7 个组件。高层图和细化图之间用编号关联,比如高层图里的“订单服务”标注为“S1”,细化图的标题就是“S1-订单服务内部结构”。这样读者可以先看全局,再看局部,认知负担可控。
3.3 视觉编码:颜色、形状、线型的语义约定
在 diagram-design 里,颜色不是装饰,而是语义。我通常约定:蓝色表示正常路径,橙色表示异步或延迟操作,红色表示异常或失败路径,灰色表示外部系统或不在本次讨论范围内的模块。形状也有约定:矩形表示服务或模块,圆角矩形表示网关或入口,圆柱体表示存储,菱形表示判断,平行四边形表示输入输出。
线型同样有语义:实线箭头表示同步调用,虚线箭头表示异步消息,空心箭头表示依赖关系,实心箭头表示数据流向。这些约定一旦确定,就要在整个项目里保持一致。我建议把这些约定写进项目的 README 或文档模板里,新人进来第一件事就是读这个约定表。
| 视觉元素 | 语义 | 使用场景 |
|---|---|---|
| 蓝色实线箭头 | 同步调用 | 服务间 RPC 调用 |
| 橙色虚线箭头 | 异步消息 | 消息队列投递 |
| 红色实线箭头 | 异常路径 | 超时、重试、降级 |
| 灰色矩形 | 外部系统 | 第三方服务、遗留系统 |
| 圆柱体 | 数据存储 | 数据库、缓存、对象存储 |
| 菱形 | 条件判断 | 开关、路由、过滤 |
3.4 布局原则:从左到右、从上到下、避免交叉
布局不是审美问题,而是认知问题。人眼阅读图形时,默认遵循从左到右、从上到下的顺序。所以主流程应该从左到右排列,分支流程应该从上到下排列。如果连线出现交叉,读者的视线就会被打断,理解成本急剧上升。
减少交叉的技巧有三个:第一,把交互频繁的节点放在相邻位置;第二,把长连线改成短连线,必要时用编号引用代替直接连线;第三,如果交叉无法避免,用“跳线”符号(一条小弧线)表示不连接。我见过最极端的案例是一张图里有 30 多条交叉线,读者根本分不清哪条线连哪个节点。后来拆成三张图,每张图只有 5 条线,问题就解决了。
3.5 标注与注释:把“为什么”写在图外,把“是什么”写在图内
图内只放最必要的信息:节点名称、关键参数、条件分支。图外放解释性内容:为什么这么设计、有哪些取舍、后续怎么扩展。我通常在图的下方加一个“说明”区域,用编号对应图内的关键节点,逐条解释设计意图。
提示:不要在节点框里写超过 10 个字。如果节点名称太长,用缩写加图例说明。比如“用户认证与授权服务”可以缩写成“Auth”,然后在图例里写“Auth = 用户认证与授权服务”。
4. 实操过程:从零开始设计一张可维护的架构图
4.1 第一步:明确图的受众和目的
在动手之前,先回答三个问题:这张图给谁看?他们关心什么?看完之后要做什么决策?如果是给开发看,重点放在接口边界和数据流向;如果是给产品看,重点放在业务流程和状态变化;如果是给运维看,重点放在部署单元和依赖关系。受众不同,图的抽象层级和视觉重点完全不同。
我通常会为同一个系统准备三张图:一张给管理层看的上下文图(只画系统边界和外部依赖),一张给开发看的组件图(画内部模块和调用关系),一张给运维看的部署图(画物理节点和网络分区)。三张图共享同一套节点命名和颜色约定,但详细程度不同。
4.2 第二步:用文本定义图的结构
以 Mermaid 为例,我会先用文本把节点和连线写出来,不关心布局。比如:
graph LR A[客户端] --> B[网关] B --> C[订单服务] B --> D[用户服务] C --> E[(订单数据库)] C --> F[库存服务] F --> G[(库存数据库)] D --> H[(用户数据库)]这段文本定义了节点和连线,但布局是自动生成的。如果布局不理想,可以调整节点顺序或添加子图。文本定义的好处是:可以进 Git,可以 diff,可以 review。改一个节点名称只需要改一行文本,不需要手动挪箭头。
4.3 第三步:调整布局和视觉编码
自动布局出来的图通常需要微调。我会检查三件事:第一,主流程是否从左到右清晰可见;第二,是否有不必要的连线交叉;第三,颜色和形状是否符合约定。如果某个节点位置不理想,可以通过调整文本定义中的节点顺序来影响布局,而不是手动拖拽。
对于需要精确控制的图,我会用 Draw.io。Draw.io 支持网格对齐和参考线,适合画需要打印或嵌入文档的架构图。我的习惯是:先用 Mermaid 快速出草图,确认结构无误后,再用 Draw.io 重绘正式版。这样避免在布局上反复调整浪费时间。
4.4 第四步:添加图例和说明
图例是图的“使用说明书”。我通常在图的一角放一个图例区域,列出颜色、形状、线型的含义。如果图中有缩写,也在图例里说明。说明区域放在图的下方,用编号对应图内节点,逐条解释设计决策。
比如:
说明:
- 网关负责鉴权和限流,不负责业务逻辑。
- 订单服务和库存服务之间是同步调用,超时时间 500ms。
- 订单数据库和库存数据库物理隔离,避免单点故障。
4.5 第五步:评审和版本管理
图做完之后,一定要找相关角色评审。评审的重点不是“好不好看”,而是“有没有歧义”。我通常会问三个问题:第一,你能用自己的话复述这张图的主流程吗?第二,有没有哪个节点你不确定它的职责?第三,有没有哪条连线你不确定它的含义?如果三个问题都能顺利回答,图就合格了。
版本管理方面,我建议把图的源文件(Mermaid 文本、Draw.io 文件)和导出的 PNG/SVG 一起提交到代码仓库。每次修改图,都要在提交信息里写明改了什么、为什么改。这样当有人问“这张图什么时候变的”时,可以直接查提交历史。
5. 常见问题与排查技巧实录
5.1 图太复杂看不懂怎么办
这是最常见的问题。排查思路是:先数节点数,如果超过 15 个,就拆图。拆图的原则是按职责边界拆,而不是按数量平均拆。比如把“订单域”相关的节点放一张图,“用户域”相关的放另一张图,两张图之间用编号引用关联。
如果节点数不多但连线很乱,就检查是否有交叉线。减少交叉的方法是调整节点位置,把交互频繁的节点放在一起。如果还是乱,就把部分连线改成编号引用,比如在节点 A 上标“→见 3.2”,在节点 B 上标“←来自 3.2”。
5.2 图与代码不一致怎么办
这是维护阶段最头疼的问题。我的做法是:把图当作代码来维护,每次代码变更如果影响了架构,就必须同步更新图。具体操作是:在代码仓库里建一个docs/diagrams目录,存放所有图的源文件。在 CI 流程里加一个检查,如果代码的模块结构变了但图没变,就发出提醒。
更彻底的做法是用代码生成图。比如用 PlantUML 或 Mermaid 从代码注释里提取结构,自动生成图。但这种方式适合结构稳定的系统,对于快速迭代的系统,自动生成的图往往跟不上变化。
5.3 不同角色对图的理解不一致怎么办
这说明图的抽象层级不对。给不同角色看的图应该有不同的详细程度。我的做法是:为每个角色准备一张专属图,但所有图共享同一套命名和颜色约定。比如给产品看的图只画业务流程,不画技术组件;给开发看的图只画技术组件,不画业务规则。两张图之间用编号关联,比如业务流程图的“步骤 3”对应技术组件图的“服务 B”。
5.4 图太多找不到最新版怎么办
这是版本管理问题。我的做法是:所有图统一放在一个目录下,文件名包含版本号和日期,比如architecture-v2.3-20250115.drawio。同时在目录下放一个README.md,列出当前有效版本和废弃版本。每次更新图,都要更新 README。
| 常见问题 | 排查思路 | 解决方法 |
|---|---|---|
| 图太复杂 | 数节点数、检查交叉线 | 拆图、调整布局、编号引用 |
| 图与代码不一致 | 检查变更记录 | 图进版本控制、CI 提醒 |
| 理解不一致 | 确认受众和抽象层级 | 为不同角色准备专属图 |
| 找不到最新版 | 检查文件命名和目录结构 | 统一命名规范、维护 README |
| 连线语义混乱 | 检查线型和颜色约定 | 统一视觉编码、写进文档模板 |
5.5 独家避坑技巧:图的生命周期管理
我踩过最大的坑是:图做完之后没人维护,三个月后连自己都看不懂了。后来我总结了一个“图的生命周期管理”方法:每张图都有一个负责人,负责人在图更新时通知所有依赖这张图的角色。图的废弃也要有流程,不能直接删除,而是标记为“已废弃”并注明替代图。
另一个技巧是:在图的标题里写上“最后更新日期”和“负责人”。这样任何人看到图,都知道它是不是最新的、该找谁问。这个习惯看起来很小,但能省掉大量沟通成本。
6. 工具链与协作流程的落地建议
6.1 轻量级方案:Mermaid + Git + Markdown
如果团队规模小、迭代快,我推荐这套轻量级方案。Mermaid 负责画图,Git 负责版本管理,Markdown 负责写说明。所有内容都在代码仓库里,开发人员不需要切换工具就能看到最新的图。这套方案的门槛极低,新人半天就能上手。
具体操作是:在docs/diagrams目录下建.mmd文件,每个文件一张图。在docs/architecture.md里用 Mermaid 代码块引用这些图。提交代码时,如果改了架构,就同步改.mmd文件。CI 流程里加一个步骤,把.mmd文件渲染成 PNG 并上传到文档站点。
6.2 中量级方案:Draw.io + 共享目录 + 评审流程
如果团队规模中等、需要精确布局,我推荐 Draw.io 方案。Draw.io 的文件是 XML 格式,可以进 Git,但 diff 不太友好。所以我的做法是:源文件进 Git,导出的 PNG 也进 Git,评审时看 PNG,修改时改源文件。
评审流程是:负责人画图 → 相关角色评审 → 修改 → 定稿 → 更新文档。评审时重点检查三件事:节点职责是否清晰、连线语义是否明确、是否有遗漏的异常路径。
6.3 重量级方案:代码生成图 + 自动化流水线
如果系统非常复杂、架构频繁变化,我推荐代码生成图方案。用 PlantUML 或 Structurizr 从代码或配置里提取结构,自动生成图。这套方案的前期投入大,但后期维护成本低。适合微服务数量超过 20 个、或者架构经常调整的团队。
具体操作是:在代码里用注解标注模块依赖,用脚本提取注解生成 PlantUML 文件,再用 CI 渲染成图。每次代码合并,图自动更新。这样图永远不会和代码脱节。
注意:代码生成图适合结构图,不适合流程图和时序图。因为流程和时序包含业务逻辑,很难从代码里自动提取。所以这套方案通常和手动维护的流程图配合使用。
6.4 协作流程:图的所有权和更新机制
无论用哪套方案,都要明确图的所有权。我的做法是:每张图有一个 owner,owner 负责图的准确性和及时更新。owner 可以是个人,也可以是小组。当图需要修改时,由 owner 发起评审,评审通过后更新。
更新机制方面,我建议把图的更新纳入需求开发流程。每个需求在开发前,先更新相关图;开发完成后,再检查图是否和实现一致。这样图始终和代码同步,不会出现“图是三个月前的”这种情况。
7. 从单张图到图系统:diagram-design 的长期价值
7.1 图与文档的联动
单张图的价值有限,图系统的价值在于联动。我通常会把图嵌入到文档里,用编号引用。比如在架构文档里写“系统整体结构见图 1”,在详细设计里写“订单服务的内部结构见图 2”。这样读者可以在不同抽象层级之间跳转,既能看到全局,又能看到细节。
联动的另一个做法是:在图里嵌入文档链接。比如在 Draw.io 里给每个节点加一个超链接,点击后跳转到对应的详细设计文档。这样图就变成了一个导航入口,读者可以从图出发,深入到任何感兴趣的模块。
7.2 图与代码的联动
图与代码的联动有两种方式:一种是在代码注释里引用图,比如// 架构见图 3.2;另一种是在图里引用代码,比如在节点上标注对应的代码路径。我通常两种都用:代码注释里放图的编号,图里放代码路径。这样开发和阅读代码的人都能快速找到对应的图。
更高级的做法是用工具自动建立映射。比如用 Structurizr 把代码结构和图关联起来,改代码时图自动更新。但这套方案的学习曲线较陡,适合对图系统有长期投入的团队。
7.3 图系统的演进:从静态到动态
静态图只能表达结构,动态图可以表达行为。我通常会用静态图表达架构,用动态图表达流程。动态图可以是时序图、状态图、活动图。对于复杂的业务流程,我还会用 BPMN 图表达。
演进路径是:先建静态结构图,再建动态流程图,最后建状态转换图。三套图共享同一套节点命名和颜色约定,形成一个完整的图系统。这样无论是新人入职、还是跨团队沟通,都能找到合适的图来表达和传递信息。
7.4 个人经验:图的质量取决于信息梳理的质量
我做了这么多年的图,最大的体会是:图的质量不取决于画图工具,而取决于信息梳理的质量。如果信息梳理清楚了,用记事本画 ASCII 图都能让人看懂。如果信息梳理不清楚,用再高级的工具也画不出好图。
所以我的建议是:在打开画图工具之前,先用纸笔或文本编辑器把节点和连线列出来。确认结构无误后,再考虑视觉编码和布局。这个习惯能帮你省掉大量返工时间。
最后分享一个小技巧:每次画完图,隔一天再看一遍。如果隔了一天你还能一眼看懂,说明图合格了。如果隔了一天你自己都看不懂了,说明图需要简化。这个“隔天测试”是我用过最有效的图质量检查方法。