diagram-design:把架构图当代码管理,文本化图表的工程之道

发布时间:2026/9/9 11:48:09
diagram-design:把架构图当代码管理,文本化图表的工程之道 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 不是某种一次性的画图比赛它本质上是让图表重新回归工程体系成为可追踪、可评审、可演进的设计产物。我自己在落地过程中最大的感受是画图这件事难的不是操作工具而是把图当成正经的工程产物来对待。当你开始为图写需求、做评审、配版本、设规范它就从一个补充说明的附件变成了辅助沟通和决策的主资产。这套方法不一定适合所有团队但只要你吃过一次文档里的图过期了的亏就值得花半天时间把工作流搭起来后面全是复利。