资讯动态

diagram-design实战:用代码画出生动有用的架构图

发布时间:2026/10/17 12:11:11 来源:尧图企业网站定制
很多人以为画架构图是天赋活其实它更像翻译活。把系统拆成一块块积木再把积木之间的依赖、流程、时序讲清楚整个过程就是 diagram-design。我最初把它当一个小工具链来折腾结果越做越发现真正难的不是画图软件而是怎么让图在团队里持续存活、持续有用。这篇文章不讲虚的直接把我做 diagram-design 的心法、实操套路、踩坑记录全部摊开适合那些被“图越画越乱、没两天就过期”困扰的开发者、产品经理和技术文档维护者。全程用大白话看完能直接用。1. 先想明白为什么画不出好图往往不是手的问题1.1 图是给人看的不是给工具看的我见过太多人一头扎进画图工具先调半天配色再拽一堆框框最后画出来一张“自我感动”图信息密度极大五颜六色自己看得懂别人一脸懵。这种问题的根源是顺序反了。diagram-design 的第一步不是打开工具而是先回答一个问题这张图要帮谁在哪个场景下解决什么困惑。举个例子。同样画一个系统架构给新入职的同事看你要突出的是“服务边界”和“调用关系”中间件细节先收起来给老板做汇报看你要突出的是“模块价值”和“演进路线”底层技术栈反而要淡化给 SRE 团队排查故障用你要突出的是“链路节点”和“监控埋点”画得越朴素越好。同一套系统至少三种画法。先想清楚受众图才有存在的意义。1.2 图文匹配先定用途再定工具画图前先给图分类。diagram-design 里最常见的几类用途我做了个简单的对照表方便你直接判断该画哪种图种解决什么问题典型场景推荐的表现方式架构图系统里有哪些模块模块之间怎么连接服务治理、方案评审分层布局 实线连线流程图一件事从开始到结束经历了哪些步骤业务流程、发布流程、审批流程自上而下或自左而右的步骤串联时序图多个角色之间来回调用消息的先后顺序接口设计、跨系统交互纵向时间轴 横向参与者状态图一个对象有哪些状态、怎么迁移订单状态、设备状态状态节点 迁移箭头数据模型图表、字段、主外键关系数据库设计、数仓建模实体关系 连线标注思维导图把一个主题拆分归类头脑风暴、需求梳理树状发散我见过不少同学把流程图画成思维导图把架构图画成脑图本质都是没想清楚“这张图到底要表达什么过程”。定好图种后面所有工作都会顺很多。1.3 一张图上信息负债的边界“信息负债”是我的一个土说法。任何一张图都有能力上限超过之后看图人得花更多力气去解读图的边际收益就变成负数。我给自己定的规则是一张图只回答一个核心问题。如果这个问题需要超过 7 个关键节点才能讲清我就拆成主图和子图。以前我在某跨平台系统的架构图里硬塞了监控、日志、缓存、消息队列、网关、权限、数据库、客户端 SDK 一共八个维度结果每次评审都要讲解十五分钟图成了“装饰墙”。后来拆成“运行时链路图”和“部署拓扑图”两张问题一下子清楚了。这个思路也适合流程图主流程超过十步就把其中的子流程单独画一张用子图编号引用而不是把所有分支都堆在同一张里。2. 拆开一张合格架构图的核心零件2.1 角色与关系节点的分类原则如果把一张图拆成最小单元无非是“节点”和“连线”。节点代表一个存在的事物连线代表它们之间的关系。diagram-design 最关键的纪律就是节点与连线的语义必须统一。节点我习惯分三类实体比如用户、订单、数据库、容器比如服务、应用、中间件、边界比如整个系统的外部依赖或者子系统边界。在图上用形状区分是最简单可靠的我建议固定一种习惯比如数据库 / 存储类节点圆柱体或带底线的容器服务 / 应用类节点矩形圆角幅度小一点更像服务外部系统类节点矩形加虚线边框强调“不归我们管”决策点菱形或其他形状只在流程图里出现。连线则分为实线依赖、虚线弱依赖、箭头单向调用、双向通信这几种。最怕的是整张图全是实线箭头没有粗细和虚实之分看起来就像一团麻绳。每一条连线都要能回答两个问题谁发起依赖的方向是什么。这里有个我经常强调的细节很多图把“依赖方向”画成“创建顺序”比如 A 创建 B 就把 A 指向 B。这是两种完全不同的语义。依赖方向表示 A 背后需要 B创建顺序表示时间前后。混在一起排查问题的人会误判。画图时要把这两类边分开要么用不同颜色要么加文字标注千万不要让读者靠猜。2.2 布局与视线不要让人绕圈好的布局应该让读者的视线顺着一条主路径走而不是来回跳跃。常见的布局有两种自上而下适合业务流程和层级结构自左而右适合时间序列和依赖链。diagram-design 里没有绝对标准但有个负面清单可以参考连线尽量少交叉。交叉不可避免时优先保证主干链路不交叉。同一层的节点尽量对齐。节点不齐的图会让人误以为有层级关系。回环和反向箭头要显式画出来不要隐藏在网络里。如果反向依赖过多可能说明模块划分有问题。不要把核心链路放在图的角落里。视线经过最多的地方应该放最重要的节点。我见过最有问题的一类图是“节点处处相等”——所有框一样大、一样颜色、一样边框读者根本看不出主次。要避免这个可以在核心节点上加粗边框或者用深浅色区分层级。但要克制核心节点不要超过三个不然到处都很重要等于都不重要。2.3 色彩与阴影的克制这里必须泼一盆冷水很多人画图难看不是因为不懂配色而是因为太想“画好看”。diagram-design 的配色逻辑是语义优先其次才考虑美观。我通常采用一套 4-5 色的固定调色板主色给核心服务次级色给支撑服务中性灰给基础设施高亮色只用于“异常路径”或“本次改造涉及节点”。全图高亮色绝对不多于 10%。阴影、渐变、圆角、立体感这些装饰能不用就不用。阴影尤其坑人在导出 PNG 或嵌入文档时经常压缩后变得一坨黑。而且很多团队用灰度打印机彩色图打印出来直接废掉。我给团队的建议是先做一个黑白可读的版本再叠加颜色信息这样在任何介质上都有底线。2.4 标签与注释图中文字的两种宿命图中的文字只有两种宿命要么是“查询用的索引”要么是“人读的细节”。索引必须精简比如“用户服务”“订单库”控制在 2-6 个字能识别即可人读的细节比如接口路径、超时时间、状态码放到注释、图例或者侧边栏里不要全塞在框内。框内文字过多是画图大忌。我给每行模拟实践时用的原则每个节点框内最多三行文字超过三行就说明这个节点承担了太多职责。比如“订单服务”这个节点你不应该在框里写“下单、支付回调、库存扣减、退款”而应该只写“订单服务”把职责清单放到旁边备注或文档里。读者先看清结构想了解细节再找注释这才是健康的阅读顺序。3. 代码画图把设计沉淀到仓库里3.1 为什么要用“图即代码”手工拖拽画图最大的问题是“不可审查”。你永远不知道这张图最后是谁改的、改了哪里、为什么改。代码画图把这个痛点解决得很彻底图的源文件是普通文本进入 Git 仓库可以做 diff、可以走 Code Review、可以在 CI 里自动导出图片。这才是 diagram-design 能长期保鲜的核心机制。刚开始团队会觉得多此一举但坚持一段时间后收益非常明显。第一改图必留痕谁动过图、动了什么一目了然第二图和代码同库存放版本天然对齐不会再出现“代码已经重构架构图还是三个月前”的尴尬第三新人可以通过读图的 diff 理解系统演进过程比翻文档高效很多。3.2 从手绘到代码的工作流我整理了一套自己的 diagram-design 工作流基本上一直这么用用白板、纸笔或在线白板先画出草稿这一步只画结构不纠结细节。把草稿的结构翻译成文本描述明确列出节点清单、边界清单、连线清单。用某种“图即代码”工具生成初版图形比如绘图语法描述类工具。对照草稿检查布局和语义调整分组、连线和样式。提交到仓库写清楚变更说明和代码一起走评审。在文档站点或 README 里引入渲染结果同时保留源文件链接。这套流程里最关键的是第二步。很多人直接从脑子想跳到工具写代码结果边写边改一团乱。先列清单哪怕用一张表格列出节点、层级、依赖也比闭上眼睛直接画要稳。3.3 文本化描述的要点节点、连线和分组这里我不依赖某个具体工具而是把通用的核心语法思路讲清楚。一般来说一个文本化图的描述由三部分构成节点定义、连线定义、分组定义。节点定义要确定唯一 ID 和显示标签ID 用于连线引用标签用于展示。连线定义要写清楚起点、终点和方向有时还要带标签说明关系类型。分组定义是为了把相关节点折叠到一个边界里比如“前端层”“服务层”“数据层”。我常用的一种描述结构如下{ title: 某跨平台系统架构图, groups: [ { id: client, label: 客户端层 }, { id: server, label: 服务层 }, { id: data, label: 数据层 } ], nodes: [ { id: app, label: 移动端, group: client }, { id: web, label: Web端, group: client }, { id: gateway, label: 接入网关, group: server }, { id: order, label: 订单服务, group: server }, { id: db, label: 订单库, group: data }, { id: cache, label: 缓存, group: data } ], edges: [ { from: app, to: gateway, label: HTTPS 调用 }, { from: web, to: gateway, label: HTTPS 调用 }, { from: gateway, to: order, label: RPC }, { from: order, to: db, label: 读写 }, { from: order, to: cache, label: 读写 } ] }这种结构的好处是和代码审查思维一致改哪个节点、加哪条边一眼就能看出来。无论你用哪种工具背后都是同一套抽象。在实际项目里我通常会额外维护一份“图例说明”把每种线型、每种颜色代表什么写清楚放在图的旁边或文档下方这样看图的人不需要猜。3.4 导出、嵌入和自动化图即代码的最终价值是能被持续集成和分发。现在多数绘图工具都支持命令行导出常见的有 PNG、SVG、PDF 等格式。我最常用的是 SVG原因是矢量图在文档里放大缩小不糊而且可以直接被网页引用。如果公司内部文档系统支持外链图片我更建议把图渲染成图片后放到对象存储里再把图片地址嵌到文档中这样既能独立更新又不会让源文件暴露给不了解的人。在自动化方面我习惯在提交代码时触发一次文档构建任务源文件变更后自动重新出图。这样永远保证 README 或设计文档里的图是最新版本。如果构建失败就把任务标红让作者先修图再合代码。这一招看起来严格其实帮团队省了大量“图过期”的沟通成本。4. 一个真实场景的完整实操给某跨平台系统画架构图4.1 业务假设与边界确认与其空讲理论不如走一遍实操。假设我们要给“某跨平台系统”画一张架构图系统包含移动端、Web 端、接入网关、几个微服务、数据库和缓存。第一步不是画图而是确认边界这张图到底覆盖到什么范围。我通常会列一个边界清单属于系统内部的客户端 SDK、接入网关、业务服务、数据存储、缓存。属于外部依赖的短信服务、推送服务、第三方支付。本次图不体现的监控系统细节、日志链路细节、内部部署拓扑。边界确认后画图时对外部依赖统一用“外框虚线”表示内部模块用实线框。这个动作能避免读者误把外部依赖当成自家服务。4.2 先列清单再造结构我会先把节点和连线写成一张关系表这张表就是画图草稿的地基。比如节点所属层依赖方向依赖对象说明移动端客户端层调用接入网关需要登录态Web端客户端层调用接入网关需要登录态接入网关接入层调用订单服务负责鉴权、路由订单服务服务层读写订单库存储订单主数据订单服务服务层读写缓存缓存热点订单查询订单服务服务层调用支付服务第三方支付封装支付服务服务层调用第三方支付外部依赖这张表写完之后结构其实已经出来了客户端层在最顶接入网关在第二层服务层在第三层数据层在最下边外部依赖放在一侧。不要小看这个笨办法它能帮你把隐藏依赖全部浮出水面而不是画到一半才发现少了条链路。4.3 用代码实现并调整布局接着把上面的关系表翻译成绘图脚本。我以一个通用的 JSON 结构做示意重点看它的分组和样式定义{ title: 某跨平台系统架构图, layout: top-down, nodeDefaults: { fontSize: 14, shape: box, strokeWidth: 1 }, groups: [ { id: client-layer, label: 客户端层, stroke: #666666, fontSize: 16 }, { id: access-layer, label: 接入层, stroke: #CCCCCC }, { id: service-layer, label: 服务层, stroke: #CCCCCC }, { id: data-layer, label: 数据层, stroke: #CCCCCC } ], nodes: [], edges: [] }这个配置文件里最重要的是“layout: top-down”它决定整体次序。如果系统的主链路是横向的比如在多个站点之间跳转我会改成 left-right。画完后第一轮渲染出来我通常会做三件事看主干链路是否顺眼看分组边框是否包裹住对应节点看文字是否有重叠。哪不顺眼就在脚本里调整而不是在成品图上用鼠标硬拖。用代码改图的好处是每次调整可回溯改坏了可以回到上一版。4.4 导出、评审和迭代初版图生成后别急着发出去。我的习惯是先邀请两个同事做“五分钟盲测”把图发给他们五分钟内回答三个问题——“系统分了几层”“流量怎么走的”“哪里容易挂”。如果三个问题答不上来说明图的信息组织有问题。盲测通过后再把图导出成 PNG 或 SVG嵌到设计文档里并且把源文件的路径一并写进文档的“更新说明”避免后人找不到原图。等系统上线新服务、调整了调用关系时改源文件重新出图再走一轮评审。长期下来这张图就成为活的架构记录而不是一次性装饰。5. 常见坑位与排查实录5.1 布局不听话节点乱跑怎么办画图时最常遇到的问题就是布局引擎给出的结果和预期不一致。你希望 A 在 B 上方结果它在侧边你希望一组节点靠在一起结果被打散。遇到这类问题我的排查顺序是先检查节点是否被正确放进同一个分组里。分组是布局的默认约束很多乱跑是因为节点没归组。再看是否显式指定了层与层之间的依赖顺序。依赖关系越强布局才会越倾向于把相关节点排近。如果还是乱就在脚本里给关键节点加位置偏好或层级权重。几乎所有文本画图工具都支持某种“可调优先级”或者手工固定坐标的机制优先给核心链路节点固定好位置其他节点再让引擎自由排。我自己踩过的坑是给所有节点都加固定坐标结果加完以后想调一个节点位置牵一发动全身。正确做法是只锁定少量骨架节点自由度留给布局引擎这样整体依然可控维护成本也低。5.2 渲染报错与显示黑屏速查代码画图偶尔会碰到渲染失败常见原因就那几类表现可能原因处理办法整张图没出来语法错误、括号没闭合用官方校验工具定位看定位行附近某个节点消失节点 ID 重复给 ID 加前缀比如 service-order、db-order中文显示为方块字体或编码问题确保导出环境装了中文字体源文件用 UTF-8线条方向反了连线的起点终点写反对照关系表逐条检查尤其注意“依赖方向”的定义图和预期位置差别大分组边界缺失或循环依赖太多抽象出单向的主链路必要时拆图中文显示问题最容易被人忽视。很多同学在本地预览正常一放到 CI 服务器导出就变成方块根本原因是服务器上没装合适的中文字体。解决方法是把字体文件一并放进构建环境或者在脚本里指定一个部署环境中确定存在的字体。这个坑不踩一次很难注意我建议在写自动化之前就把它纳入检查。5.3 协作冲突多人改一张图如何不打架只要把图放进 Git 仓库多人协作就可能出现冲突。文本画图工具的好处是冲突可以像代码一样合并但前提是大家遵守同样的修改习惯。我的一些约定一个文件一个模块尽量不把多个系统的图塞在同一个文件里。图太大时拆文件通过引用方式组合。修改节点或者连线时保持每个节点写一行不要一行塞多个定义方便 diff。每次提交只改一个意图比如“新增支付服务节点”和“调整下单链路方向”不要混在一次提交里。冲突出现时不要凭记忆硬解。先和对方确认这个改动的业务意图再决定保留哪个方向。如果团队里很多人不熟悉文本画图还有一个过渡方案图仍然用可视化工具维护但定期把导出的源文件快照提交到仓库作为存档。这样至少保留了历史版本只是失去了精细 diff 的能力。等团队上手后再彻底切换。5.4 图太大了拆成多张的时机什么时候该拆图我有个经验阈值当一张图上的节点超过 20 个或者有读者反馈“太挤”的时候。拆图不是简单分两张而是要顺着读者的心智拆。比如一个订单系统你可以拆成“下单主流程”“支付回调流程”“售后流程”三张三张图共享同一个“订单服务”的图例与配色。然后做一张总览图上面只有“客户端/网关/订单服务/支付/售后”五个节点每张子图在总览图上有对应的链接。读图的人先看总览再按需点进子图负担瞬间下降。拆图之后最难的反而变成了“如何保证多张图信息一致”。我会定期用脚本检查不同图之间是否有 依赖矛盾。比如子图 A 说订单服务依赖缓存子图 B 却没画缓存这就是不一致。现在不少团队会直接用文本方式维护每张图指向同一个共享配置从源头避免不一致。6. 最后再分享几个压箱底的习惯做 diagram-design 越久越觉得图的价值不在画得炫而在画得“省脑”。我最后分享几个长期好用的小习惯。第一个习惯是维护“术语表”。每个团队都有自己的内部叫法比如“某某服务”“某某中台”如果没有统一术语三张图里会出现三个名字都指同一个东西。我的做法是在仓库里放一个术语映射表画图时必须用术语表里的规范名别名一律不出现。刚开始会有点麻烦但图一旦被文档、PPT、故障排查反复引用术语统一带来的收益非常大。第二个习惯是给图加“修改日期”和“负责人”。图一旦多人维护一张图的原点责任必须明确。不是说要卡住修改权限而是要有一个默认的 owner当图出现争议时知道找谁问。很多团队图烂掉就是因为“人人能改人人不负责任”。第三个习惯是定期做“图体检”。我每隔一个季度会挑一天把所有架构图和当前线上实际情况对一遍把已经下线、改名、重构的节点全部标出来然后一次性更新。这个体检不要缩减成“没有 bug 就不动”架构图是需要主动养护的资料等它彻底过期再更新成本会高得多。最后一个只做不说的小技巧画完图后关闭编辑器打开成品图从左上角到右下角快速扫一遍想象自己是一个完全不了解系统的新人。如果你在哪停顿了超过三秒那里就加注释如果你觉得“这里为什么要这样画”说明图形语言没表达清楚。这个“陌生人视角”的自检每次都能帮我发现几个隐藏盲点。diagram-design 说到底不是画图技术而是把复杂系统翻译给另一颗大脑的艺术。多画、多拆、多回看时间会给你答案。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑