diagram-design 这个名字乍一看挺唬人,好像是什么高端设计理论。其实说穿了就是画图——把架构图、流程图、时序图、ER图这些技术图表,从随手一画的草稿,变成一套有规范、可维护、能进版本库的设计资产。
我在项目里被图坑过太多次了。环境一变更,文档里的架构图要么没人更新,要么某个人用 Visio 改了一版,发到群里就再也找不到最新版。后来我花了小半个迭代的时间专门收拾"图"这件事,沉淀出一套自己的工作流,也就是标题里这个 diagram-design 的东西。今天把它拆开讲透,工具、流程、坑,一次说清楚。
1. 为什么图表设计值得被当成正经事
1.1 一个把架构图画废了的惨痛经历
先讲一段真实经历。去年做一个订单中台重构,整个系统拆成 7 个微服务加两个消息队列,我在 PRD 里放了一张架构图,是用 Draw.io 拖了大半天拖出来的。好看是真好看,圆角方块、彩色分组、带箭头编号,自己看着挺得意。
结果上线前做容量评估,技术评审会上架构师指着图问:"订单落库之后的消息路由走的是 Kafka 还是 RocketMQ?这图上只画了 MQ 一个框,我根本看不出来。"当时我愣了一下,往下一看,图里确实是只写了"MQ",因为拖拽的时候懒得改文本,想着反正后头有文字说明。
这就是典型的问题:图好看,但信息不准确、层级不清楚、无法快速定位。从那次之后我把所有的架构图全部推倒重来,也因此在团队里立了一个规矩——图表不能是"画出来的",它必须能像代码一样被审查、被维护、被自动化检查。
1.2 diagram-design 解决的三个核心问题
我理解 diagram-design 这个词,不是某个工具,而是一整套关于"如何设计一张好图"的工程方法。它解决的核心问题有三个。
第一个是信息准确度。图里的每个框、每条线都必须对应真实存在的模块或数据流,不能有"看起来差不多"的模糊表达。第二个是可维护性。图不应该是一次性产物,它要能跟着代码迭代一起更新,随便让谁接手都能在十分钟内改明白。第三个是可传递性。一张好图应该能脱离作者独立存在,读者不需要作者在旁边讲"这块当时我没画清楚"就能看懂。
这三个问题叠加在一起,就引出了最核心的做法:把图当作一种文档代码来管理,而不是当作图片来管理。
1.3 图表也是一种代码资产,不是一次性草稿
很多人画图的心态是"把当前结构记录下来",图是文档的附属品,实在没地方放才放一张图。但我觉得反过来才对——图是理解系统的重要入口,文字才是补充。
代码能做的事,图也应该能做:能 diff、能 review、能回溯历史版本、能量化维护责任。如果你画完图就把源文件删了,只留一张 PNG 在文档里,那它迟早会变成一个无人维护的"历史遗物"。正确做法是把图的源文件当成和代码同等级别的资产,放进仓库,纳入评审,有变更就有提交记录。
判断标准很简单:你现在的架构图源文件在不在版本库里?如果答案是不在,那它大概率已经过期了。
2. 拿到一个设计需求,先做信息架构而不是急着画框
2.1 先理清受众和表达目标
设计一张图之前,第一件事不是打开工具,而是问自己:这张图是给谁看的?
这个问题虽然听着像废话,但绝大多数画得烂的图都是因为答错了这个问题。给技术评审看的系统架构图,关注的是服务边界、依赖关系、数据流向;给运维排障看的链路图,关注的是节点、端口、健康检查路径;给新同事做 Onboarding 用的模块图,关注的是模块之间调用的主流程。
我习惯在动手前先把受众写下来,一句"这张图给谁看、看完要能回答什么问题",想不清楚这个,后续所有设计都是空的。
拿架构图来说,一种常见分类可以区分三层:容器层(系统间的关系)、组件层(系统内部模块的关系)、类/接口层(代码级别的细节)。给老板看的是容器层,给开发看的是组件层,给码代码的人看的是类图。一张图试图同时满足三层受众,结果就是谁都没法用。
2.2 信息层级:哪些内容进图,哪些进文字
图本身不是越全越好。我发现很多开发同学画图有个冲动:把所有东西都想塞进去,恨不得把数据库索引、连接池数量、日志级别全标上。结果整张图密密麻麻,反而丢失了重点。
我的经验是给信息分三级:
- 一级信息:这张图的核心故事线,必须一眼能看出来,比如服务调用的主链路。
- 二级信息:支撑理解的上下文,比如外部依赖、配置中心、网关位置。
- 三级信息:具体数值和参数,这些坚决不进图,放到图下方的说明文字或表格里。
这其实是把"图"和"文档"分工了。图负责呈现关系结构,文档负责解释细节约束,两者互相补充,谁也不替代谁。
2.3 一张图一个故事:限定复杂度
再补充一个我自己定的硬性指标:一张图最多放 7 个主节点。如果超过 7 个,就说明这张图的故事太多,要把它拆成两张以上。
这个 7 的数字不是玄学,来自认知负担的经验值——人眼的短期记忆容量大概就是 5~9 个信息块,超过这个阈值,看图的人就要不断回看前面的部分,理解成本陡增。
如果你的系统就是有 14 个服务,怎么办?拆。先画一张"总览图"只画 4 个核心域,再为每个域单独画一张内部交互图。总览图讲边界和流向,细节图讲接口和依赖,读者按需查看。这样每一张图的信息量都受控,而且后头的维护也会轻松得多。
3. 工具链选型:把图表文本化的三种主流方案
3.1 为什么我不建议主力用拖拽式画图工具
很多团队还在用 Visio、Draw.io、ProcessOn 这类拖拽式工具。我不否认它们的易用性——拖个框、连条线、改个颜色,上手成本极低。但我坚持团队主力图必须用文本化方案,原因有三。
一是拖拽图的 diff 能力太差。你改了一个箭头方向,整个文件可能有十几个字符的坐标变化,review 的时候根本看不出改了什么。二是拖拽图很难自动化。你想在 CI 里检查图里必须包含某个服务节点?做不到,因为图文件本质是一坨 XML 坐标数据,没法做语义断言。三是拖拽图的版本管理形同虚设。两个人同时编辑同一张图,合并冲突能让人崩溃,最后往往变成"谁先保存谁赢"。
当然,拖拽工具没有完全被淘汰,它们适合做一次性、快速表达想法的草图。但在正式项目里,我会把文本化方案放在第一位。
3.2 文本化方案横向对比:PlantUML / Graphviz / Mermaid
目前主流的文本化图表方案我重点用三款,各有所长。
PlantUML是我最常用的。它语法简单,支持时序图、用例图、类图、状态图、组件图等多达十几种图类型,Jar 包一个命令就能渲染。它最强的点是:用简单的文本描述就能生成还算体面的组件图和时序图,团队不需要额外学习太多概念。
Graphviz是底层图渲染引擎,用 DOT 语言描述节点和边,布局算法非常成熟,特别适合那种节点多、关系乱、需要自动排布的依赖关系图。它的语法比 PlantUML 更底层,但换来的是对布局的精细控制,比如用 rank 控制层级,用 subgraph 做聚类。
Mermaid胜在和 Markdown 生态的融合,在 GitHub、GitLab 的 Markdown 里可以直接渲染,适合写在 README 和 Wiki 里,团队阅读成本为零。但它的复杂图类型支持不如 PlantUML 全面,遇到特殊布局时容易力不从心。
我给团队的建议是:画业务时序图和组件图用 PlantUML;画依赖分析和拓扑结构用 Graphviz;写文档里的简单流程图直接用 Mermaid。
3.3 版本管理与团队协作:图表进 Git
不管选哪种方案,源文件一定要进 Git,这是 diagram-design 的根基。源文件进 Git 之后,你能获得几个实打实的好处。
评审变简单了。改动从"你截图我猜"变成"我直接看 diff"——比如你在组件图里加了一个 Redis 集群节点,review 的人能清楚地看到多了一个框、两条边,上下游关系一目了然。历史可回溯。三个月后有人问"当时为什么把订单查询拆出去了",翻 Git 记录就能看到当时的图改动和 commit message 对应起来。自动检查也能做了。可以写个脚本扫描源文件,检查图里的节点命名是否合规、是否包含必填的服务标识,不达标就在 CI 里报错。
我把这套流程固化在一个模板仓库里,新项目建起来,自动带上图表目录和一个 Makefile,执行一条命令就能把所有文本图渲染成 PNG 和 SVG,交付物统一收在dist/文件夹。这个习惯给我省了无数沟通成本。
4. 实操全流程:从零到一张可交付的架构图
4.1 需求梳理与草图阶段
再好的工具也替代不了需求分析。我通常按下面四步走,每一步都留有产物,方便回头检查。
第一步是明确核心问题,用一句话写下这张图要回答的问题,比如"下单之后的数据如何流经全部服务"。
第二步是列出参与元素,把涉及的服务、存储、消息队列、外部系统全部列出来,先不用管画法,纯粹是清单。清单用表格管理,每条记录包含元素名称、类型、职责说明。别小看这个表格,它就是图的"数据源",后面作图时,每个节点都必须能在这个表格里找到对应项。
第三步是画出关系,在清单里标出元素之间的调用、依赖、消息订阅关系。我用一对多的列表记录,每条关系写清楚方向、类型、是否同步。这一步做完,图的骨架就已经定了。
第四步才是正式作图。因为前边的清单和关系已经把所有信息整理好了,作图只是把结构化描述翻译成目标工具的语法,速度快得多,而且不容易漏东西。
4.2 落地代码、参数调整与渲染
示意图可以用代码写了。我以一个 PlantUML 组件图为例,先把核心结构写出来:
@startuml skinparam componentStyle rectangle skinparam backgroundColor #FFFFFF package "客户端层" { [Web 前端] as WEB [App 客户端] as APP } package "接入层" { [API 网关] as GW } package "业务层" { [订单服务] as ORDER [库存服务] as STOCK [支付服务] as PAY } package "数据层" { database "订单库" as ORDER_DB database "库存库" as STOCK_DB } WEB --> GW APP --> GW GW --> ORDER GW --> STOCK ORDER --> PAY ORDER --> ORDER_DB STOCK --> STOCK_DB PAY --> ORDER : 支付结果回调 @enduml这段代码看着不长,但有三个容易踩坑的参数点。
skinparam componentStyle rectangle把默认的组件图标改成矩形,视觉上更简洁,适合架构图;skinparam backgroundColor统一背景色,避免渲染出来是刺眼的黄白色;用as给每个元素起别名,这样在复杂图里调整连接关系时不需要反复写字面名称。
布局调整是新手最头疼的地方。PlantUML 的自动布局算法一般够用,但当节点多、边交叉的时候,我通常用两个办法:一是在需要同层排列的节点之间加隐藏边,用[hidden]关系强制对齐;二是直接给连线加left、right、up、down方向。这里有个经验:先靠自动布局,除非真的很乱,不要手动指定方向,不然以后每次加节点都要重新调一遍方向,维护成本翻倍。
4.3 校验、评审与发布
成图之后不是直接丢进文档就完事,我有一套三关卡流程。
第一关是信息完整性校验。把图导出成 SVG 之后,拿它和第一步的需求清单比对:清单里的元素是否都能在图上找到,有没有哪条关系线漏画了。这一步可以用脚本半自动做,写个小程序解析源文件里的节点名,再和清单 CSV 做 diff,缺了哪个直接标红。
第二关是评审。把图源文件和渲染出来的图一起提交 MR,邀请对应模块的负责人 review。重点看三件事:关系是否正确、命名是否一致、是否有隐藏的循环依赖。循环依赖在图上经常被忽略,我在代码里会写一个检查脚本,扫描关系列表找出 A→B→A 的环,评审前先自查掉。
第三关是发布。图渲染成 SVG 放文档站点,同时把源文件放仓库。SVG 的好处是缩放不糊,而且能被搜索引擎索引文字内容,适合放在在线文档里。发布之后更新文档里的引用链接,把源文件路径也写进去,这样后来的人才能"从文档反查到源文件",这是可持续维护的关键一步。
5. 常见问题与排查技巧实录
5.1 布局乱成一锅粥怎么办
文本化工具最让人崩溃的就是布局。明明逻辑是对的,渲染出来边全绕在一起,节点间距忽大忽小。
我先说排查顺序。第一步,检查是不是有孤立节点——没有任何连线的节点,它会自己飘到一个边角,直接把布局带偏。孤立节点如果是暂未接入的预留模块,我习惯用一个可见性很低的虚线框单独标注,而不是裸露着放在图里。第二步,检查是不是有超长文本节点。PlantUML 默认不会自动换行,一个写了几十个字的服务名会把整行撑开,影响一排节点的对齐。解决方法是用\n手动换行,或者在 skinparam 里设置maxMessageSize这样的参数,控制文本宽度。
第三步,如果布局实在调不回来,我的终极办法是调整图的叙述方向。PlantUML 支持top to bottom direction和left to right direction,把纵向布局改成横向,很多交叉问题会自动消失。比如业务调用链从左到右画很顺,但一旦涉及数据库回写,改成从上到下反而清晰。多试几个方向,不要死磕其中一个。
5.2 图太大、信息塞不进去怎么办
这是最普遍的诉求:"能不能把 20 个服务画在一张图里?"能,但不建议。前面说过一张图一个故事的原则,当一张图超过 7 个主节点,正确做法是分层拆解。
具体拆法我提供一个可执行的分层框架:
- L0:生态全景图,画外部系统、本系统核心域、数据流向,不涉及内部模块。
- L1:系统蓝图,画本系统的所有服务、存储、消息组件与依赖关系。
- L2:域内交互图,画某一个域或某一个服务内部的模块与调用。
实际操作中,我在 L1 碰到节点太多的情况,会先把相关服务归组成子图,PlantUML 用package或rectangle包裹即可。归组之后,视觉上的信息块从 20 个变成四五个,读者先看组间关系,再展开看组内细节。这样既保持了全貌,又降低了理解难度。
有个小技巧:每一层图的源文件放同一个目录,命名用
L0-ecosystem.puml、L1-blueprint.puml这种带层级前缀的格式。读者按文件名就能自选阅读深度,维护的人也知道改动应该落在哪一层。
5.3 团队协作里的维护难题
文本化方案最大的协作痛点不是画图,而是没人愿意在下次变更时更新源文件。人的惯性很强大,图能用就绝不主动改,哪怕源文件就在仓库里。
我的解决办法是给"图变更"建立刚性的触发条件。在代码评审的 MR 模板里加一个勾选项:如果本次改动涉及服务拆分、接口变更、数据存储调整,必须附带更新对应的架构图源文件,否则 MR 不能合并。这个规则一开始会有人嫌烦,但跑两个迭代之后,持续更新图就成了团队的习惯,新来的同事甚至默认"文档里那张图就是最新的"。
另外一个容易被忽视的维护点是视觉风格统一。多人写图容易各写各的,有的人用矩形,有的人用圆角,有的人给节点加奇怪的缩写。我在仓库里放了一个公共的 skin 文件,统一管理字体、颜色、间距等样式,所有图都!include这个文件。效果类似前端项目里的全局 CSS 变量,改一次全图生效,视觉一致性立刻提升一个档次。
5.4 一份我踩出来的避坑清单
最后把我这几年在 diagram-design 上踩过的坑整理成一份清单,供你对照使用。
- 不要把图和文档放在两个系统里管理。图应该嵌在文档附近能引用的地方,至少保证文档指路到源文件。
- 不要用图片格式存终稿。PNG 和 PDF 适合交付阅读,但源文件必须保留,否则任何小改都要从零开始。
- 不要让复杂图依赖自动布局。凡事超过 15 个节点的图,建议手动归组、手动指定关键方向,别全靠布局算法。
- 不要忽略文字标注。节点命名用全称,至少一眼能看出职责,短缩写真的会害死人。
- 不要在一张图里混合多种抽象层次。数据库的表级细节和服务级节点放在一张图里,读者会被迫在两个层级之间反复切换。
- 不要等图过期了才重画。每次需求变更时顺手改图,比几个月后花半天重画整个图要省事得多。
这几条每一条都是真金白银换来的教训。比如"不要用图片格式存终稿"那条,我见过一个项目里的架构图,是同事从旧文档里截出来的低分辨率 PNG,放大全是马赛克,还找不到源文件,最后只能按现网代码重新逆向画了一遍,可以想象有多痛苦。
6. 把 diagram-design 落地到你的项目里
工具和方法讲了不少,最后说说具体怎么落地到自己的项目。我建议分三步走,不用一步到位。
第一步是挑一个正在活跃迭代的项目,把现有的架构图画成文本源文件放进仓库。优先选你最熟的模块,画错、画漏都不可怕,迭代中会自然纠偏。第二步是在文档里换上这张图,并删掉旧图片文件,从物理上切断"旧图还在"的退路。第三步是约定一个变更触发规则,比如凡是涉及服务间调用变更的 MR 必须更新图,先跑两周看效果,再决定要不要推广到别的项目。
如果你已经有一堆存量系统,我建议不要急着全部迁移。选一个正在重构、变化最快的项目做试点,跑通之后再慢慢铺开。diagram-design 不是某种一次性的画图比赛,它本质上是让图表重新回归工程体系,成为可追踪、可评审、可演进的设计产物。
我自己在落地过程中最大的感受是:画图这件事,难的不是操作工具,而是把图当成正经的工程产物来对待。当你开始为图写需求、做评审、配版本、设规范,它就从一个"补充说明的附件"变成了"辅助沟通和决策的主资产"。这套方法不一定适合所有团队,但只要你吃过一次"文档里的图过期了"的亏,就值得花半天时间把工作流搭起来,后面全是复利。