ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

技术图设计指南:信息压缩与Mermaid实战,让架构图一眼读懂

技术图设计指南:信息压缩与Mermaid实战,让架构图一眼读懂 HTML渲染之前的一分钟我还在改图。不是改配色是改结构。这个场景你可能也熟技术方案评审前一天对着白板拍了张照片回工位用PPT重新画边画边发现少了一条链路补上之后又发现交叉线多到没法看最后只能靠“箭头绕半圈”糊弄过去。评审会上对面的架构师盯着图看了五秒问了一句“这个依赖是谁发起的”我看了一眼自己画的“架构全景图”恨不得当场隐身。后来我花了不少时间琢磨 diagram-design 这件事不是学怎么把圆形和矩形排列得更漂亮而是搞清楚一个问题——为什么有些图一看就懂有些图看了半小时还找不到重点。答案是好的图不是画出来的是设计出来的。你先把信息选对了、层次切好了、读图顺序理清了后面上颜色、调字体都是水到渠成的事。这篇文章就是我在这个方向上踩过坑、也沉淀下来的一套可复用的方法。适合常年写技术方案、画架构图、画流程图、画时序图的人不管是程序员、产品经理还是运维工程师看完至少能把“画图”变成“设计图”让读者在三十秒内抓住你想说的那件事。1. 为什么我把 diagram-design 看作工程问题而不是绘图问题1.1 从一次失败的技术方案评审说起那次评审印象太深了。我花了三个晚上画了一张“系统全貌图”想给领导展示我们系统的完整能力结果投影仪一开屏幕上密密麻麻全是节点和箭头领导坐第一排都得眯眼。其中一个服务我只画了名字没写清楚职责被问到底暴露了哪些接口我对着图念了三十秒。问题不是我不会画图而是我把图当成了“系统的照片”以为把现实原封不动搬上去就完成了任务。实际上 diagram-design 的第一步不是添加信息而是删除信息。你删掉的东西越多留下来的信息才越值钱。那次之后我给自己定了一条规矩一张图只回答一个问题宁可画十张单点图也不再追求一张“包含万物”的宇宙图。1.2 图是一种信息压缩不是信息堆砌人脑的工作记忆容量非常有限。心理学里的经典研究说大多数人同时只能记住 4 到 7 个信息块你往一张图里塞进三十个节点对读者来说这不是信息丰富而是认知负担。图之所以有价值是因为它可以压缩复杂关系把原本需要三千字描述的系统交互压缩成一条主链路上的几个节点和箭头。所以我会先问自己这张图给谁看他看完之后要做什么判断给技术委员会看重点是分层和边界体现系统的扩展性和风险点给刚接手的新人看重点是核心路径和模块归属帮助他建立心智地图给运维看重点是部署依赖和流量方向。目标读者不同同样的系统画出来完全是两张图。1.3 可读性与可维护性两个核心约束我评价一张技术图只有两个指标。第一个是可读性一个不熟悉业务的人不看任何解释三分钟内能不能明白图标之间的关系。如果三分钟之后还要问“这个框代表什么”“这条线什么意思”说明图的编码规则失败了。第二个是可维护性当业务发生变更时你更新这张图需要多久。如果是手动拖拽的图工具每次改一个节点要重新拉线、调整布局、处理交叉线十分钟起步如果图是用文本描述的改一个名称、删一个依赖就是一次字符替换重新生成就完事还能放进代码库里做版本管理。这也是为什么我后来把所有要长期维护的图都迁移到了文本化方案上因为 diagram-design 如果只考虑当下画出来不考虑半年之后怎么改那这张图的寿命基本也就两周。2. 工具选型实录代码生成、白板绘制与矢量手绘的取舍2.1 代码生成方案Mermaid、Graphviz、PlantUML 的定位差异我早期选工具是看哪个火用哪个后来发现不同工具的布局算法和语法设计差异极大决定了它们适合的图完全不一样。Mermaid 是目前社区热度最高的方案语法接近自然语言写文档时可以直接内嵌在 Markdown 里。它尤其擅长流程图、时序图、状态图这种“线性叙事”的图。优点是上手快、渲染干净适合放在 README 和技术方案里缺点是自动布局能力偏弱图一复杂节点就乱跑你只能通过调整代码顺序来影响布局。Graphviz 走的是另一条路线它暴露了 dot 语言你可以为每个节点指定层级rank然后用引擎自动规划布局。它的强项是处理节点多、关系密的图比如类依赖图、拓扑关系图、数据流图再复杂的连线它也能给你算出一个基本不交叉的布局。但成本也高语法比较底层的写起来有门槛而且输出风格偏学术。PlantUML 在 UML 圈子里地位很高类图class diagram、用例图use case、时序图这些它都有专用语法语义化程度高。但它的渲染风格老气在线环境有时还得装依赖所以我个人只有在要交付 UML 图的时候才用它。2.2 白板协同方案Excalidraw 与 diagrams.net有时候你需要的不是一张交付图而是一个讨论介质。这时候我会打开 Excalidraw它的手绘风格让人没有距离感团队在画布上写写画画比面对一个“正式”的架构图更容易产生讨论欲望。这个工具的最大价值是“低心理负担”但它几乎没有自动布局能力也不适合放进 Git 里做文本 diff图一复杂调整一次线的代价很大。diagrams.net旧称 draw.io功能更全界面和 Visio 风格接近内置了大量图标适合画网络拓扑、机房部署这类需要大量形状素材的图。但它的核心问题在于文件格式是 XML虽然也能存文本但可读性差评审时看 XML diff 等同于没有 diff。2.3 我的选择标准工具选型没有标准答案但可以按图的“生命周期”来判断。我会先问这张图是要长期存在还是讨论完就丢如果它属于文档体系的一部分、会被后来的开发者查阅和修改那必须选文本化方案Mermaid 是默认选项需要复杂布局时用 Graphviz。如果它只是为了某一轮方案讨论目的是对齐想法那 Excalidraw 这类白板工具效率更高。如果团队里所有人都在用统一的建模工具那你没得选工具服从团队协作。还有一个隐性成本要注意每个团队成员的本地环境能不能顺利渲染这些文本图。我见过团队里有人提交了 Mermaid 图但评审工具不支持渲染最后又是截图贴上去版本管理直接失效。所以在这个问题上我强烈建议提前跑通 CI 里的导出流程确保每次提交都能自动生成 PNG 或 SVG。3. Mermaid 实战从文字到图的五步设计法3.1 第一步确定图的类型而不是先画节点很多人画图一上来就摆节点摆到最后发现要表达的东西变了。我的习惯是先用一句话描述这张图要讲的关系再选图类型。如果我要讲“一次调用请求经过了哪些服务、每个服务返回什么”那是时序图sequenceDiagram。如果我要讲“某个流程有哪些分支不同条件下走哪条路”那是流程图flowchart。如果我要讲“系统在什么状态下响应什么事件、状态之间怎么迁移”那是状态图stateDiagram-v2。如果我要讲“实体和实体之间一对多还是多对多”那是 ER 图erDiagram。选错图类型是硬伤。有一次我见到有人用流程图画状态机每个状态画成一个节点迁移条件全写在箭头上结果一个状态机画出来十几条线错综复杂还不如直接用状态图圆角矩形再加一个箭头就表达清楚了。3.2 第二步围绕一条主链路组织节点确定类型之后我会先画出主链路也就是说哪怕这张图里只有 5 个节点它们也要构成一条能看懂的故事线。举一个真实的例子。某次我画一个用户下单流程一开始把支付、库存、优惠券、通知、对账全部揉在一张图里结果主路径完全被支线淹没。后来我重新整理只保留一条主线用户提交订单 - 订单服务创建订单 - 调用支付服务 - 支付成功回调 - 通知用户下单成功。库存扣减和优惠券结算全部作为旁路放到图的下方或者干脆用第二张图描述。主线是图的脊柱读者第一眼扫过的时候会优先沿着这条线读其他支线只有需要对比时才出现。如果一张图的开始节点和结束节点离得很远且中间绕了三道弯那说明主线没理清楚。3.3 第三步控制节点信息密度每个节点承担的信息量要克制。我给自己定的标准是节点名称不超过六个字中文且尽量是一个动词短语或一个名词短语。“校验用户权限”可以作为一个起点但“判断当前用户是否为已认证状态下并同时校验用户角色权限然后返回对应结果”已经没有资格当节点名称。节点信息过载还有个隐蔽问题它模糊了节点边界。读图者看到一个大长句时不知道这算一步还是三步后面的连线也就失去了意义。如果这个长句里确实有多个步骤那就拆成多个节点或者把它降级为一个子图里面再细化内部步骤。3.4 第四步用子图表达边界和层次Mermaid 的 subgraph 是我最常用的结构性工具。一个典型的三层架构如果不用子图你只能依靠节点名称前缀来区分层比如“user-service”“order-service”“payment-service”读图者要自己归纳太累了。用了子图之后边界变得一目了然外层是网关层中间是业务服务最下面是基础设施。不过子图有个副作用一旦开始用就忍不住多用结果整张图被框子塞满。我的建议是子图数量不要超过 4 个每个子图内部的节点数量同样遵循 7±2 原则否则子图的存在就没有信息增量。3.5 第五步迭代渲染与视觉验证写完之后一定要反复渲染。第一次渲染之后我会闭上眼睛想一下——如果我不是作者看到这张图我的视线会从哪里开始接下来会去哪里如果第一眼看到的是外围装饰节点而不是主入口就需要调整节点在源码里的声明顺序。Mermaid 的布局受节点声明顺序影响很大把主链路的节点放在最前面往往能让它们出现在图的核心区域。视觉效果上我还会检查三点有没有悬空的边、有没有完全重叠的节点标签、线的交叉是不是已经到了影响阅读的密度。交叉线很难完全避免但至少不能让交叉发生在主干道上。如果主干道交叉严重就提前拆主次链路别硬塞进一张图。4. 布局与视觉设计远比换颜色更重要的事4.1 方向与阅读顺序读图和读书一样有天然的阅读方向。中文世界的读者习惯从上到下、从左到右所以你的图也最好像文本一样沿着这个方向展开。流程图和时序图涉及时间推进方向更不能乱。我见过把主流程画成 U 字形、然后箭头还要从下往上折回来的图读者注意力直接被截断。解决这个问题最简单的办法是在 Mermaid 里显式声明方向flowchart TB 表示从上到下flowchart LR 表示从左到右。复杂图建议用 TB因为竖向空间通常比横向更充裕节点换行文案也更容易处理。4.2 交叉线处理交叉线是图可读性的头号杀手特别是在依赖关系复杂的系统图里。两个办法可以显著降低交叉。第一个办法是拆分。一张图如果出现了多处“跨区域连线”说明这个区域划分可能和真实依赖关系不匹配你该做的是重新调整子图划分把依赖紧密的节点放进同一个区域。第二个办法是加中间层。两个子图之间如果需要频繁交互不要直接在每个服务上都拉线那样会形成一团乱麻。比较好的方式是引入一个消息层或网关节点所有的交互都通过这个中间节点转发。虽然多了一个节点但线的数量从 N×M 条变成了 NM 条视觉上清爽了不止一个量级。4.3 视觉重量与配色语义一张图里有重点就得有“视觉重量”的差异。重要节点可以加大字号、加深边框或者填充强调色次要节点默认样式就好。最怕的就是整张图所有节点都用同一种高饱和颜色填充看下来一片花花绿绿根本没有焦点。配色最好带语义。正常路径用中性色或冷色异常路径或风险路径用暖色待办或未实现的部分用虚线加浅色。这个约定要提前在图的标题或图注里说明否则读者只能靠猜。技术图不是海报颜色不是拿来装饰的是拿来编码信息的。4.4 文字可读性节点里文字太长、太小、太密是常见通病。我自己定了条规矩节点内文字单行最长不超过十个字超过就换行或缩写。如果确实有一大段说明放在图下方的图注里而不是塞进节点。还有一点容易被忽略中英文混排时中文与英文之间要有一个空格这样视觉上不会挤在一起。导出图片时优先 SVG 格式SVG 里文字是矢量放大缩小不糊PNG 适合发到聊天窗口预览但放大后文字发虚。4.5 布局迭代的投入产出比钻研布局细节是有边际收益递减的。我的态度是图的结构正确了布局做到“不干扰阅读”就可以收手不值得为了“对称美观”再花半小时调整像素。真正复杂的系统美观是排出来的不是画出来的。好布局来自好结构好结构来自信息取舍。5. 从“一张图”到“一套图系”处理复杂系统的分层叙事5.1 用 C4 思路拆解复杂系统当系统规模大到一张图确实装不下的时候我会引用 C4 model 的方法论。它把系统拆成四个层次系统上下文Context、容器Container、组件Component和代码Code。每个层次对应不同的读者和粒度。上下文图只画一个大方框标出系统与外部用户、外部依赖的关系容器图把系统拆成服务、应用、数据库组件图继续拆到服务内部的模块代码图才会画到类级别。我在实践里并不会严格套用四层但这个思路非常有价值先画大而全的上下文图再逐层深入。读图者先建立边界感再了解内部结构符合认知规律。5.2 每张图只能有一个中心思想我经常提醒自己图是论据不是目录。一个章节里的架构描述可以用一张图表表达模块依赖再配一张时序图表达某个关键流程而不是试图用一张图把整个章节的内容全部概括。所以我在写技术方案时图的数量往往超过预期但每张图的篇幅都很短读者反而觉得比一大张全景图更友好。5.3 图与文档必须联动维护图脱离了文字很容易失真。我见过太多同事辛苦画了架构图但库里代码早就改了图还停在半年前的状态。要解决这个问题最有效的办法是把图嵌在文档里、文档跟着代码走变更代码时自然能看到图的 diff。我用 Mermaid 的体验是图的变更可以和文档一起 review摘掉节点、新增连线一目了然。这和“截图贴进 Word”的做法完全不同后者没法做版本管理最后图一定先腐烂。6. 我踩过的坑与调试清单6.1 中文字体渲染异常Mermaid 默认渲染在浏览器里看起来正常但一旦用脚本导出 PNG 或 PDF中文字符经常变成方块乱码。这是我在 CI 导出时遇到过最坑的问题原因是执行导出的环境缺少中文字体最终渲染时找不到对应字形。解决方法是给导出环境安装中文字体比如 Noto Sans CJK 或 WenQuanYi并在渲染配置里指定 fontFamily。还有一个更省事的方式导出别追求 PNG直接用内嵌 SVGSVG 里字体引用一般不会出乱码。如果你一定要输出多页 PDF 给客户评审那就提前在下游设备上验证一遍渲染效果。6.2 时序图的参与者过多导致的乱麻画时序图最舒服的规模是 4 到 6 个参与者。服务一多箭头和生命线交叉几乎没法读。有一次我画一个分布式事务的时序图画了 8 个参与者结果关键的回滚链路完全淹没在横向线条里评审的时候根本没人注意到。后来我改用“角色合并”策略非关键的服务合并成一个带有池语义的参与者比如“下游系统”只有核心流程中的关键服务才单独画出生命线。或者干脆拆成两张图一张画正常提交路径一张画异常回滚路径。读者在两个时间段分别读比一次性接收两条并行链路容易得多。6.3 方向不听话时的处理Mermaid 的自动布局偶尔会不按照你的书顺序来尤其是流程图分支一多节点经常跑到意料之外的位置。遇到这种情况不要硬靠样式调先用方向声明LR/TB把全图方向固定下来再调整节点的定义顺序。如果还不理想就用子图把“应该在一起”的节点先圈起来。我见过最离谱的一次一条回环箭头跨过了整个图的主干道怎么看怎么别扭。后来发现根因是子图嵌套层级太深布局引擎计算顺序错乱。把子图层级从三层改成两层之后问题消失了。复杂图遇到布局异常先简化结构通常能解决。6.4 节点成了段落而不是事实很多人画流程图时喜欢把业务规则写成一整段话放进节点比如“如果用户有未完成的订单且下单时间超过三十分钟则释放库存并发送提醒”。这个节点该不该拆看它是否包含两个以上的动作和两个以上的条件。如果包含拆分。拆成“检查未完成订单”“判断超时”“释放库存”“发送提醒”四个节点不只图面清爽逻辑也更严谨因为拆分的过程中你可能发现自己遗漏了某条路径。6.5 升级依赖导致的老图语法失效Mermaid 版本更新频繁偶尔会出现语法不兼容。最常见的是老的图配置项失效、某些标签不再支持。我建议团队锁版本不要随便 upgrade升级时跑一遍所有图文件的渲染脚本出问题提前发现。这和图的结构设计无关但属于 diagram-design 工程化的最后一公里不做的话图库就是定时炸弹。7. 关于 diagram-design 的几个个人习惯先写一段文字再画图。这个习惯帮我避开了至少一半的结构性问题。文字描述里的主语和动词会自然暴露图里的节点和连线文字里的转折关系通常对应图里的分支和判断。如果你用三段话描述一个流程最后却画不出对应的图说明这段文字本身的逻辑是有洞的画图本质上是在给自己做逻辑体检。把图当成代码来维护。图的文件放在 docs/diagrams 目录下命名里带业务模块和日期改图走正常提交流程谁改的图、为什么改都能在提交说明里查到。这张图在团队里才有生命力而不是某一个人脑中的孤本。保持“每张图只解决一个问题”的原则。复杂系统不是靠一张图传达的是靠一组图表达出来的。就像地图软件会把卫星图、路网图、交通流量图拆开给你看你不会要求一张图同时承担三个功能。diagram-design 的技术含量不在鼠标上在你的取舍判断上。把这点想通了你画的就不再是“示意图”而是真正能辅助决策的设计图。
返回列表