
做了这么多年开发和架构设计我发现一个挺反直觉的事实很多技术方案最终不是输在了代码上而是输在“讲不清楚”上。不管是评审、汇报、交接还是新人 onboarding一张架构图、流程图往往决定了对方愿不愿意继续听你说下去。这也是为什么我对 “diagram-design” 这件事越来越较真——它不是什么锦上添花的美术课而是工程师表达能力的一部分是实实在在的沟通效率工具。这篇文章我想把过去几年在“画图”这件事上攒下来的经验整理一遍包括最核心的思维方式、工具选型逻辑、排版配色细节、代码化维护方案以及那些不踩一遍根本不知道的坑。如果你是那种“工具都会用但画出来的图总差点意思”的人或者正在纠结团队文档里的图应该怎么统一管理这篇应该能帮你在思路上理清不少东西。先说个结论画图这件事90%的问题出在画之前而不是画的时候。1. 图表设计的核心逻辑与思维模型1.1 动笔之前先回答三个问题我见过太多人打开画图工具就开始拖框框拖了半小时发现布局乱了再拖一小时开始烦躁。根本原因不是手笨是脑子没想清楚。我自己这几年的习惯是画图前先在文档或者聊天框里写一句话说明“这张图到底要讲什么”。如果这一句话写不出来那说明你在动笔之前其实并没有把逻辑理顺。写这句话的时候至少要把下面三个问题一起想清楚这张图是给谁看的技术评审、产品对齐、新人培训、对外分享四类读者关心的东西完全不一样。读者想从图里带走什么信息评审关心模块划分和依赖关系产品关心业务主线新人关心从哪开始看代码。哪些内容是这版图必须表达的哪些是多余信息有时候不是信息太少是信息太杂。举个例子我在给某个模拟项目X做架构梳理时第一次画的图把所有内容都塞进去了接口调用、数据库表关系、消息队列消费顺序、权限模型、异常重试机制。结果评审会上每个人提问点都不一样——有人问存储有人问链路有人问权限。后来把一张大图拆成三张独立视图一张业务流程、一张部署架构、一张核心时序效率明显高多了。我个人的原则很简单一张图只说一个主逻辑。凡是需要读者“绕来绕去”看的东西要么拆图要么做成图组。1.2 三张底层思维模型流程、结构、协作做了大量 diagram-design 相关的实践后我发现虽然图表的样式千变万化但底层逻辑基本就三类流程模型、结构模型、协作模型。流程模型回答“事情按什么顺序发生”。节点之间的连接是“先后、分支、并行”。典型代表业务流程图、时序图、状态机图。结构模型回答“谁包含谁、谁依赖谁”。核心是层级、父子、包含关系。典型代表组织架构图、模块结构图、目录树、ER图。协作模型回答“多个角色如何配合完成一件事”。核心是角色、职责、消息交互。典型代表系统架构图、泳道图、部署拓扑图。我画图前会先判断当前要表达的领域本质属于哪种模型这个判断直接决定布局策略——流程模型适合线性或分支布局结构模型适合树形或嵌套布局协作模型适合分区加横向/纵向泳道布局。如果硬把流程模型画成树形或者把协作模型画成纯线性读者理解起来就会很吃力。这里有个很实用的技巧先画出模型草图再考虑美化。模型是有问题的后面再好看也没用。反过来模型对了哪怕画得朴素也基本能看懂。1.3 一张好图的三个可检验标准我在团队里定了一个“30秒法则”任何人拿到这张图30秒内要能准确说出这张图的核心逻辑。为了落地这个法则我把判断标准拆成三条可验证的指标图中使用的符号、缩写、自定义概念是否超过两处如果超过第一件事不是做图例而是简化表达。如果把图转成文字描述信息量和原图是否一致经常出现的问题就是——图里看上去很完整但关键的约束条件、异常分支只存在于画图人的脑子里图上根本没体现。读者闭上眼复述一遍是否能复述出主干链路复述出来的内容和你的预期是否一致这是检验信息传达效果最直接的方法也是团队评审时最容易暴露问题的方式。1.4 图表和文字的分工还有一个认知我花了很久才想通图不是用来替代文字而是用来和文字分工的。图负责“关系、路径、结构”这类整体性信息文字负责“边界条件、参数细节、动机解释”这类局部性信息。一张图配一小段说明文字永远优于“只有图没有任何解释”或者“只有文字完全无图”两种极端情况。在写技术文档时我通常会用图表达“骨架”再用表格或列表表达“细节”。比如架构图表达组件间关系下面的数据表字段清单才是细节补充。这比试图在架构图里把字段也标出来清晰得多。2. 工具选型没有最好的工具只有最合适的2.1 主流图表工具横向对比很多人第一个问题就是“用什么工具画”。我长期深度使用过的工具有几款每款的脾气摸得都比较清楚简单做一个横向对比工具适合场景最大优点最大短板Excalidraw快速草稿、白板讨论、方案原型上手极快手绘风格缓解沟通压迫感复杂图形与样式规范较弱draw.io常规架构图、流程图、免费交付免费支持离线可嵌入多种平台默认模板样式偏老审美上限有限Figma高保真交付、UI/UX与架构图结合图层、组件、设计变量体系庞大对纯技术人学习成本偏高Mermaid文档内嵌图、代码化维护文本化、易diff、可自动渲染复杂布局与精细样式能力有限PlantUMLUML、时序图、组件图UML元素类型最全自动布局中文渲染与样式定制麻烦Graphviz复杂拓扑图、大规模自动布局布局算法强适合节点多的图语法晦涩手工调细节非常痛苦2.2 为什么我强烈推荐“代码化图表”如果在“长期维护”和“一次性展示”之间做选择我的判断标准越来越倾向于能代码化就代码化。理由特别现实代码化图表可以进版本库每次变更都有 diff能回滚能追溯“上一版为啥这么画”。文档和图的生成流程可以自动化。文档更新图跟着重新渲染不用手动同步。多人协作时不冲突还是会冲突但冲突是能解决的如果是二进制文件或手绘源文件冲突基本无解。我切身体会最深的例子之前维护一份包含部署架构图的设计文档早期用 draw.io 画每次架构调整要手动改图、导图、同步到文档。后来迁到 Mermaid 文本方案架构升级时只改几个节点名重新渲染即可。虽然初期写代码比拖拽慢但后期每次变更省的时间都是肉眼可见的。2.3 工具选型的决策清单为了不让自己和团队陷入选择困难我总结了三道判断题回答完基本就有答案这张图未来会不会被反复修改会 → 选代码生成方案Mermaid / PlantUML不会 → 手绘工具随便用。读者需不需要在线交互或者多人实时编辑需要 → draw.io / Figma / Excalidraw不需要 → 静态导出的 PNG/SVG 完全够用。团队里有没有人能维护图表源代码有 → 代码化方案收益最大没有 → 可视化拖拽工具更现实。还有一条来自实践的忠告一旦团队定了主打工具和备用工具就别频繁换。最差的不是选了一款不够强大的工具而是大家各自为政——有人用这个、有人用那个最后每张图都要问“源文件在哪、哪个工具打开”。3. 高质量图表的设计原则与实操要点3.1 布局让阅读顺序符合人眼习惯图表的阅读顺序设计是大部分人忽略但影响最大的环节。人的视线习惯从左上到右下扫描。画图时尽量顺应这个习惯主流程从上到下或从左到右铺开分支和辅助信息放在两侧或下方最重要的链路放在视觉中心区域。多个节点的排列方式我一般遵循三条规则同一层级、同一声明的节点使用相同的尺寸和形状避免读者误以为不同形状代表不同含义。节点间距保持均匀不要有的挤在一起、有的散到天涯间距本身就是一种信息提示。主链路用更粗的框线或更深色块区突出辅助链路、注释、备选路径用浅色弱化。没有主次感的图看着再精致也难读。我以前画鉴权链路时把正常登录链路放在正中各种异常分支、降级逻辑挤在左右两侧。结果每次评审听众都会被密密麻麻的分叉带偏。后来调整策略正常链路用粗框大字号异常分支收敛成区域并用浅色小字标注。图面的信息密度没变但大家的注意力终于集中在正确的地方了。3.2 配色克制是最高级的审美配色是我认为被吐槽最多、也最容易改好的环节。很多人一打开工具看到几十个颜色就像逛颜料店恨不得全部都用上。结果就是图面五颜六色读者不知道该看哪里。我现在的配色规范特别简单基本不超过5种颜色主色1种用于核心模块/主链路通常是品牌色或最克制的中性深色。辅助色1-2种用于次要模块、附属功能饱和度更低。语义色固定红色 异常/拒绝/危险黄色 警告/重试/等待绿色 成功/正常灰色 禁用/历史/非本次主线。这里有个特别重要的原则不要只靠颜色传达关键信息。因为团队里有色弱同事也可能是黑白打印的文档。关键区分最好同时用形状、线型、加粗来辅助表达颜色只是锦上添花。我自己踩过这个坑以前用“红框/绿框”区分成功和失败状态对方是色弱用户看图全靠猜后来换成“红色实线 红标”和“绿色虚线 绿标”才解决问题。3.3 字体与命名细节决定专业感字体方面中文场景下优先使用系统默认中文字体避免渲染环境缺字体导致乱码或方块。图表中如果涉及代码片段代码部分用等宽字体其他描述性文字用常规字体。字号严格分层标题 图例 节点文字 辅助注释同一层级字号必须一致。命名规范是真正拉开普通图和专业图差距的地方。我给自己和团队定了一个简单的句式规矩节点名称一律用“名词短语”比如“订单服务”“支付网关”“消息队列”。连线/动作描述一律用“动词短语”比如“校验Token”“写入缓存”“调用回调”。动词方向必须和箭头方向一致不要出现箭头向右、文字写“从左调用”这种歧义。这样整体读下来一张图就像一句完整的话“客户端 → 校验 → 网关 → 调用 → 业务服务 → 读写 → 缓存”。这个表述习惯能让团队里所有人画的图保持高度一致阅读成本大大下降。3.4 一致性比风格统一更重要的一件事这里的“一致性”不只是图形和颜色统一更指的是“边界”和“约定”的统一。每张图都要有明确的边界这个图覆盖什么范围、不覆盖什么范围最好在标题或副标题里直接写清楚。最怕出现的情况是图名为“订单系统架构”实际上把埋点系统、监控系统、权限系统也全画进去了读者根本分不清主从关系。另外凡是图里出现了非通用缩写或自定义名词必须配图例或注释。比如“LBS”到底指什么“GW”是网关还是灰度不要默认读者和你拥有相同的上下文。图例体积很小但节省的沟通成本非常大。4. 核心场景实操从零到一用代码生成一张架构图4.1 场景定义一个典型 Web 应用核心链路为了把前面讲的思路完整串起来我做一次完整实操为一个典型的 Web 应用核心链路绘制一张可维护的架构图。场景设定客户端访问业务系统请求先经过网关网关做通用鉴权再转发到业务服务业务服务依赖缓存提升性能最终数据持久化到数据库。这个场景足够简单又能覆盖 diagram-design 中分区、连线、样式定制、导出、版本化等关键环节。核心目标不是画一张多么复杂的图而是产出一份可复用、可 Review、可跟随代码一起演进的基础设施图。4.2 实操步骤拆解我的完整步骤是这样的供大家参考确定主逻辑。用一句话描述链路客户端 → 网关 → 鉴权 → 业务服务 → 数据存储。列出全部组件清单。命名、职责、依赖。组件粒度以“读者能理解”为准不要细到类名或字段级别。设计分区策略。把组件按接入层、应用层、数据层组三个子图分区内调整水平或垂直排列。编写图表源码。用文本方式表达节点、连线和关系。渲染导出。生成 SVG/PNG 并嵌入文档。做可读性自检。按30秒法则检查主链路是否清晰图例和名词是否完备。4.3 源码示例与逐段说明我以 Mermaid 语法为例这是目前文档嵌入场景最省心的方案flowchart LR subgraph 接入层 Client[客户端] Gateway[API网关] end subgraph 应用层 Auth[鉴权服务] Biz[业务服务] end subgraph 数据层 Cache[(缓存)] DB[(数据库)] end Client --|HTTPS| Gateway Gateway --|校验Token| Auth Gateway --|转发请求| Biz Biz --|读取/写入| Cache Biz --|持久化| DB逐段拆解一下上面这段源码flowchart LR表示这张图是横向流程图“LR”代表从左到右布局。如果你希望纵向阅读可以改成TB从上到下或BT从下到上。对“客户端→服务端→数据层”这类调用链LR比较直观。subgraph 接入层产生一个带标题的分区把属于同一类别的节点装进去。这个分组能力非常有用它实现了我在设计原则里强调的“分区”思路。节点命名时采用Client[客户端]这种语法格式方括号表示矩形节点也可以用Client(客户端)表示圆角矩形用Client[(客户端)]表示圆柱形常用于数据库。连线用--箭头上的文字用|...|标注比如--|校验Token|这个文字就是动作或数据说明。文本中的中文除了渲染时可能会遇到字体问题外语法层面完全支持。如果你的渲染环境支持样式定制还可以加上classDef给不同分区的节点统一着色例如classDef app fill:#e8f4fd,stroke:#1976d2,stroke-width:2px; classDef data fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px; class Auth,Biz app; class Cache,DB data;第一行定义一个名为app的样式浅蓝填充、深蓝边框、加粗边框线。第二行定义data样式浅灰填充、中性边框。第三四行把对应节点归到样式类里。4.4 时序图表达交互先后顺序的利器如果架构图表达的是“谁和谁有连接”那时序图表达的就是“它们在什么顺序下、各自做了什么”。跨服务调用的场景里时序图的价值甚至超过架构图因为它能把“调用顺序”和“返回值”表达得很清晰。时序图可以这样描述上面的链路sequenceDiagram participant C as 客户端 participant G as API网关 participant A as 鉴权服务 participant B as 业务服务 C-G: 发送请求 G-A: 校验Token A--G: 校验结果 G-B: 转发请求 B--C: 返回响应participant声明参与者-表示同步请求--表示异步返回。时序图的好处是可以精确表达顺序适合在方案评审时展示核心交互逻辑在排障时也能快速定位哪个环节出问题。4.5 版本化与自动化流水线图表代码写完之后真正让它发挥长期价值的是接入版本管理和自动化流程。我建议把图表源码直接放在文档仓库中与设计文档同级目录。比如docs/ ├─ architecture/ │ ├─ overview.md │ └─ overview.mmd.mmd文件保存源码.md文件写设计说明并引用渲染好的图片。每次修改.mmd后重新渲染图片替换文档中的图片引用。进阶做法是在 CI 里加一步自动渲染任务检测到.mmd文件变更时自动渲染出 SVG/PNG、放入产物目录、更新引用。这样团队里所有人都只需要维护源码图片永远是最新版本。这也是我建议“能代码化就代码化”的最大理由图永远和代码同步而不是变成一个容易失真的静态文件。5. 常见问题与排查技巧实录5.1 节点文字被截断或挤压这是我在长时间使用代码类图表工具时遇到频率最高的一个问题。表现是节点里的文案明明不短但渲染后文字溢出边框或者几个字挤成一团。最常见的两个原因一是渲染容器宽度过窄给了节点固定宽度后文字自动换行或截断二是文本里包含了特殊字符比如引号、HTML标签导致渲染解析出错。解决办法分几步确认关闭节点固定宽度让容器自动适配文本长度如果工具支持 wrap 属性优先开启自动换行。检查文案里是否有未转义的特殊字符尤其注意引号“”和“”这类符号。如果确实需要长文本干脆不要让节点承载完整句子把细节移到图下方的注释或表格里。5.2 中文渲染成方块代码类图表在本地渲染时中文一般没问题但一旦放到 CI 环境或服务器容器里就会频繁出现中文变成“方块/问号”的翻车现场。原因特别简单渲染环境里没有安装中文字体。排查和修复路径在渲染容器的系统里安装中文字体比如常见的开源中文字体或系统自带的字体包。或者通过配置给图表指定fontFamily让渲染进程知道该用哪个字体。在本地调整完样式后记得检查导出 SVG 时是否嵌入了字体否则换一台机器打开还是可能显示异常。我踩过一次很深的坑本地渲染一切正常推到 CI 构建后架构图里的中文全变方块导致发布版文档直接翻车。后来在构建脚本里明确安装了字体并锁定生成环境才彻底解决。5.3 代码化图表的“脏 diff”多人维护同一个.mmd文件时经常出现一种尴尬情况这次代码改动其实只加了一个节点但 diff 里全是样式和换行变化。原因基本都是“有人手动格式化过”“有人顺手改了缩进”“有人重新自动排版了”。应对方式有三个团队统一格式风格尽量使用同一套格式化工具。所有成员修改后先格式化再提交避免无意义的差异。把大图拆成多个小型.mmd文件。按模块或子域拆分每个文件职责单一改一处只动一个文件。在 Review 时明确区分“内容变更”和“格式变更”格式变更不影响行为的直接通过不要陷入无意义的争论。理论上内容变了就提交这是代码化图表的核心价值但配合上述管理习惯才能走稳。5.4 图纸评审最尴尬瞬间同事说“我看不懂”这不是他能力不行而是你的图信息层级出了状况。遇到这种情况建议不要急着解释而是让他用自己的话复述这张图讲了什么然后对比他的理解和你原本的意图差在哪。我的经验是首次复述通常能轻易找出两三个“表面清晰、实际歧义”的位置。例如两个组件之间画了双向箭头但没说清楚哪个是主调用或用了某个内部代号“中转机”没写全称同事以为是某个公共服务。这个问题最好的解决方案是在画完图后找一个人做测试成本和收益完全不成正比。我在每次画完关键图后都会相邻位置找一位同事“看图说话”通常半分钟就能判断出图有没有硬伤。5.5 常见问题速查表把上面散落的经验整理成一张速查表方便大家排障时直接对照症状可能原因处理措施图面看上去很乱无从读起没有分区泳道元素全部平铺用子图或分区把组件分层主次链路分开主流程不明显主链路和其他元素等权未做强调用边框、粗细、深色突出主线弱化辅助颜色太多视觉疲劳滥用颜色表达语义颜色收敛到5色以内用形状/线型辅助区分文字密密麻麻看不清节点文本太长信息密度过高节点文案精简化细节放表格或注释每次协作改图都冲突文件管理混乱缺少版本化方案统一工具或迁移到代码化方案 自动格式化中文渲染异常渲染环境缺少中文字体安装系统字体指定 fontFamily5.6 最后两个容易忽略的实战细节还有两个细节虽然不太起眼但对图表的可用性影响很大。第一不要省略“网络边界”和“安全边界”。很多人画部署架构图时默认大家知道内外网划分结果把外部用户请求和内部服务调用画在同一条线上。等部署出现问题排障的人第一反应就是看这张图怎么画边界——如果图上没有边界排查效率会大打折扣。第二不要在架构图里顺手把“数据表关系图”也画进来。很多初学架构图的人容易把 ER 图思路混进来在模块节点下面挂一串数据表字段。架构图的主逻辑是组件协作数据表关系应该在单独的 ER 图里表达。一张图混入两种逻辑阅读成本直线上升。我个人在实际操作中的体会是“画图能力”不是美术能力而是思维能力的外显。真正重要的不是你会用多少种工具、能画出多精致的样式而是你能不能把复杂系统简化成读者能看懂的逻辑结构。我复盘自己这些年画的图进步最大的阶段恰恰是开始用“先想后画、代码化维护、画完找人试读”这套方法以后。最后再分享一个我自己坚持了很久的小习惯画完一张重要的图打印一份贴在工位或者放进文档首页第二天再来看一眼看自己还能不能在30秒内复述出主线。如果做不到说明这张图还有优化的空间。这个简单的习惯帮我发现了很多当时觉得完美、实际上充满歧义的设计图。画图的本质是降低沟通成本能让人看懂比什么都重要。