资讯动态

从画图到设计:用文本化DSL把架构图变成可维护的工程资产

发布时间:2026/10/15 8:25:36 来源:尧图企业网站定制
平时我见得最多的“图”不是最终文档里那张漂亮的架构图而是评审会上被临时画在白板上的方框加箭头。主讲人一边画一边改台下的人一边看一边猜。等会议结束没人记得箭头谁指向谁只记得“好像讲了一个方案”。后来我在自己的项目里强制把画图环节前置并且全部用文本化方式设计才意识到一件事diagram-design 不是美术工作它是把复杂系统压缩成一张可讨论图纸的信息设计过程。这篇文章就想聊聊我怎么把“画图”变成“设计”、把“图片”变成“资产”的实操经验。适合经常画架构图、业务流程图、部署图的产品、研发和解决方案同学参考。1. 从“画图一时爽”到“设计有章法”diagram-design到底在解决什么问题1.1 图是思考工具不是汇报装饰我先抛一个观点一张图最脆弱的时刻就是它画完的那一刻。因为画完以后大家马上盯着它提问而你如果只是随手拖出来的方块很难经得起连续追问。第一次产生这种感受是某次讲解订单系统改造。白板上有五个服务、四条数据库、一堆消息队列我画到第八个箭头的时候自己都分不清有一条线是“调用”还是“订阅”。后来我把同样内容用文本DSL重新写了一遍每条关系都必须写成一行明确语义的句子结果发现问题出在有一项依赖实际上是双向调用之前在白板上一条单向箭头完全表达不了。diagram-design解决的不是美观问题而是信息完整性与一致性问题。图上每一个图形都必须回答问题这个对象是什么和谁发生关系关系是什么类型。做不到这一点的图无论配色多好都是无效图。所以我更愿意把diagram-design看成一种思考工具在画图的过程中逼你把隐藏假设暴露出来。只要你的箭头含糊一次设计就会含糊一次。很多开发者习惯先写代码后补图图只是外置文档但真正有效的做法是让图先诞生用图来验证思路代码只是图的具体实现。顺序反了图的纠错价值就荡然无存。1.2 文本化是工程化第一步为什么强调文本化因为图片格式很难做工程管理。想象一下你收到同事发来一张架构图PNG想提修改意见只能在聊天里说“右下角那个框标错了”。对方改完发来一个新PNG你根本不知道他改了哪里。如果图是文本源码就能像代码一样逐行审阅、自动比较、留下评论。我所在的团队很早之前就约定架构图、时序图、状态图全部以文本文件入库不允许提交导出后的图片作为唯一真源。术语上这种用特定语法描述图形的方式常叫DSL制图。它的核心思路很简单——用结构化文字定义节点和连线渲染引擎负责画布布局。下面是一段极简示意text格式不是某个具体工具[用户] --调用-- [订单服务] [订单服务] --发布-- [订单事件] [订单事件] --触发-- [库存扣减]三行文字表达了一个清晰链路。你能在代码评审里看到这三行改动可以问“订单事件触发库存是同步还是异步”。图一旦变成文本就有了讨论的锚点。这就是工程化基础。更进一步文本图还可以通过脚本批量检查有没有孤立节点、有没有指向不存在的目标、有没有重复连接。这些检查写起来并不复杂但用图片根本没法自动化。所以我认为只要图需要长期维护文本化就应该是默认选项而不是备选。2. 工具链与工作流为什么我放弃了拖拽画布2.1 拖拽画布的三个隐性成本早期我也用通用绘图工具拖框后来发现有三个成本长期被忽略。第一维护成本。框和线的位置是一次性动作只要需求变一次布局就得重新调一次一个二十节点的架构图每次改完都像玩一笔画。第二评审成本。图片文件无法diff两个版本之间只能肉眼对照眼神差一点就会漏掉一条新增的虚线。第三复用成本。每次都要从零重新画一遍类似的组件没法抽取一个公共模块更没法动态生成多张图的联动关系。这三个成本在单张图上感受不明显一旦图的数量上到几十张全部变成负资产。文本化DSL则不同布局是引擎自动算的用户表达的只有语义。我修改一行文字增加一个节点引擎自动重排。有人担心自动布局不如手工排得好看这很真实但我接受的代价是语义关系稳定布局变化可接受。这类似于写代码和用Word排版写代码的区别——前者真正在构建逻辑后者把大量精力耗在对齐美观上。时间长了你会发现自动布局恰恰逼你放弃“用手摆放”的执念转而关注结构本身而结构才是图的灵魂。2.2 适合文本化制图的典型场景并不是所有图都适合文本化。如果核心诉求是自由表达、随意涂鸦拖拽画布反而更好如果要输出规范化模型文本化胜出。我给自己定的选择标准是三条是否要长期维护是否会被多人修改是否要嵌入技术文档。满足其中两条就优先使用文本化。典型的适合场景包括系统架构图、部署拓扑图、时序图、状态机图、业务流程图。这些图都有明确节点和连线适合用结构化描述。不适合的场景产品概念草图、手绘风的用户旅程地图、需要大量自由注释的灵感板。这类图重点在“感觉”而不是“准确”即便强行文本化也只是收获一个难用的玩具我不建议在工具上给自己找不痛快。另外还有一个容易被忽视的维度图的“生命周期”。一次性的临时讨论图白板效率最高要持续演进的系统蓝图文字化几乎是唯一可靠载体。我的建议是两类图分开管理临时图拍完照就让它消失正式资产必须进入版本库。很多人把临时图截图贴在文档里半年后没人知道它是临时的才酿成误导。2.3 图谱文件工程化管理目录、命名、版本选完工具更重要是组织文件。很多人的图都躺在“未命名00.png”“最终版01.png”里这等于没有管理。我的做法是开辟独立的diagrams目录按业务模块分文件夹。每个文件命名包含场景和作用例如order-core/architecture-overview.txtorder-core/flow-order-create.txtorder-core/state-order-status.txt文件内第一行写目标读者第二行写关键图例然后再写正文。每次改动随代码分支提交PR里可以看见图片内容的变化。这里有个小技巧文件头加一行last-review: 2024-03-20逼着团队定期检查过期图。这个习惯让我少被很多旧架构图误导。版本管理我完全依赖代码仓库的分支和tag而不是复制“最终版副本”。当业务大版本升级时我会把当前目录复制为archive-2024-v1给老图一个完整归宿。清楚知道老图在哪里新图才敢放手改。3. 一张高质量diagram的完整设计流程3.1 动图前先回答三个问题拿到需求先不要急着画先回答三个问题这张图给谁看想让他看完做什么决定他需要知道多细这三个答案不同出来的图完全不同。例如给新同学看的模块概览可以把中间件都合并成一个“基础设施”节点给运维看的部署图则必须画出每个实例、端口和依赖顺序。层次也可以分系统上下文图所有外部角色和系统、容器图主要技术模块、组件图内部模块交互。大多数人的问题不是信息太少而是把三个层次的图揉在一张图里。画图之前先选好层次能避免一半的布局灾难。我见过太多“全图”一个框里塞了十几个微服务每个下面又列了数据库、缓存、消息队列最后连作者本人都不敢保证每条线的方向是对的。正确做法是先画一张上下文图只表达“用户、系统、外部依赖”三者关系再按业务域分别画内部图。图层级之间用链接互相引用而不是复制粘贴。记住一张图只负责说服一个读者做出一个判断其余信息全部留给其他图。3.2 布局与连线语义优先于美学布局的目的是让读者不费劲地找到阅读路径。我看图时优先遵守几条原则上下方向表达调用链或时间顺序同一水平的节点表示并列核心服务放中间外部依赖靠边箭头永远指向数据或控制流方向而不是“相关”这样的暧昧关系。以下格式是我常用的文本化写法[客户端] --HTTPS-- [网关] [网关] --RPC-- [订单中心] [订单中心] --事件-- [消息中心]每条线都明确标注传输方式不让读者猜。如果节点超过十五个我用大括号把同类节点包成组。比如“中间件组”内部有缓存、消息队列、日志对外只显示为一个组细节另画子图。这既是布局技巧也是信息过滤技巧。连线标签也要讲究尽量用一句话主谓宾描述而不是只写“数据”“调用”这种没营养的词。标签写到哪里往往就逼着你把这个问题想清楚这俩到底是怎么发生的同步还是异步协议是什么写不出来说明关系还没定义好。3.3 视觉规范颜色、字体、图例一个都不能少技术图不需要五彩斑斓但必须有稳定的视觉语言。我建议定义一套极简色板主色表示核心模块中性灰表示基础设施黄色表示需要关注的风险项蓝色表示外部集成。全图颜色不超过四种也不要用太接近的两种颜色否则色盲读者会直接失明。字体统一标题字号比正文大一号即可。每个diagram的右下角固定放一个图例解释实线、虚线、彩色节点分别代表什么。这样新读者不用靠上下文猜。如果团队有前端组件库或品牌色直接沿用保证图和产品对外视觉一致。没有强制要求时从系统里复制已有的颜色值不要靠肉眼取色。这里要特别说一句图例不是可选项。很多人觉得大家都懂所以省略图例但不同人对虚线有不同理解。有人认为虚线是异步有人认为虚线是“可选调用”。一旦图例缺位这些歧义会长期潜伏。我的习惯是在文件头部写死了五种线型定义引用其他文件时也一致。如果有人私自发明新线型评审阶段就会被打回。3.4 导出交付从源码到文档的无缝衔接完成图以后很多人的做法是“截图发群里”。我建议多走两步。第一步选择格式如果是网页或技术文档导出SVG如果是聊天和演示导出PNGdpi要设成150以上避免发出去变糊。第二步嵌入文档时写清楚这张图对应的源码路径。比如文档配图下写一行“源码见 diagrams/order-core/architecture-overview.txt”。读者看到老图时可以顺藤摸瓜改源码而不是复制到画图工具里重画。需要特别注意隐私导出前检查节点名、IP、Token等敏感信息历史上有过把内网地址画进去的错误。还有图里不要用看不懂的缩写如果不得不用在第一次出现处标注全称。交付物不只是一张图而是一组配套信息图片、源码路径、适用版本、审查日期。我自己在发布文档前会跑一遍渲染脚本把生成的SVG和PNG都留档。这样即使有人改了源码导致渲染失败文档里仍能显示上一次正常版本避免线上文档突然图裂开。4. 我在实际项目中踩过的坑问题速查与排查思路4.1 布局乱成蜘蛛网怎么办大概率是节点数量超过工具自动布局的合理范围。单个图里超过二十个具体节点自动布局基本就会乱。我的处理步骤先数节点如果超了拆成多层图如果没超改成按业务流程从上到下或从左到右排列仍然乱就强制指定节点分组把关系紧密的放进一个子图。自动布局不是万能它不懂业务。比如两个模块逻辑相邻但业务上应该分属两个泳道这时候需要手动分组。在DSL里显式声明分组是布局的第一步不要指望引擎能理解“这个接口属于前端那个接口属于后端”这类领域知识。一条很实用的经验当图被反复调整布局都难看往往不是布局算法的问题而是节点数量或分组错了。我见过最严重的案例一张支付链路图有四十多个节点十几个跨线怎么看都像意大利面。后来拆成“下单流程”“支付渠道”“对账任务”三张图问题立刻消失。少即是多在diagram设计里不是美学口号而是认知规律人的工作记忆只容得下少量元素。4.2 连线复杂到看不清是谁指向谁连线乱通常有两个原因一是关系表达粒度太粗一个节点与几十个节点都有连线二是没有区分关系类型。第一种情况引入中间集散节点比如把“所有服务都发邮件告警”简化成“服务 -- 告警中心 -- 渠道适配器 -- 邮件”一下子从多对多变成一对多。第二种情况强制自己为每条线写标签写着写着就会发现有些线根本不需要画出来因为标签解释不清楚。线实在太多时不要试图在一张图里表达完切一个“数据流视角”和一个“控制流视角”读者更容易接受。还有一个经常被忽略的技巧把双向箭头拆成两条单向边并且标注不同颜色或线型。很多人用一条双箭头表示“调用并回调”这其实是两个独立交互混在一起永远说不清。我在设计接口时要求每条边必须有明确发起方和接收方这样渲染出来的图天然清晰也顺便帮我发现了很多双向依赖的设计坏味道。4.3 多人协作后风格开始失控几个同学分别画三张图色号不同、箭头含义不同整合到一起非常痛苦。我们后来做了几件事第一在公共模块定义统一主题颜色、线形、字体全部走公共变量第二把图例做成模板文件每个新图必须复制模板头部第三code review时增加检查项“图例是否完整、是否与规范一致”。让规范长在公共文件里而不是写在文档里后者没人看。另外当一个人总是修改另一个人图的布局时停下来看看是不是图太拥挤往往调整信息层级比调整坐标更有效。协作中最怕的就是“我觉得好看”。好看是非常主观的规范才是客观的。我把规范做成模板文件后新人出图的效率提升了非常多而且不需要我逐条标注“虚线不要用红色”“字体用统一字号”模板直接约束住。图例变了模板一变所有引用模板的图全部跟随。这就是文本化的红利可以定变量可以继承可以模板化。4.4 渲染和导出永远差最后一步常见现场本地渲染正常导出PDF后发现边界截断或是在PR里看是好的发到聊天工具里被压缩成一团糊。原因是画布尺寸和字体渲染差异。我的排查顺序先检查文本是否过长超过一定字数会被截断改为缩写加图例再检查画布边界设置预留5%-10%的padding最后检查字体——中文字体在某个渲染器里行高不同会导致上下错位。如果所有都正常换一个渲染后端试试很多DSL制图工具支持多渲染后端不同后端的布局有差异需要统一在CI里固定渲染版本避免“昨天能跑今天不行”。下面把高频问题整理成速查表方便现场排查现象可能原因典型排查动作布局乱节点过多或缺少分组拆图、加子图分组线重叠多对多关系未收敛引入集散节点中间层风格混乱多人各自定义颜色使用公共主题和模板导出截断画布padding不足调整边界余量缩小文本字号中文乱码/错位字体缺失或行高差异固定字体资源统一渲染环境渲染结果不稳定工具版本升级锁定CI中的版本号这张表看起来很简单但我自己在实际项目里至少每条都踩过两遍以上。尤其是“渲染不稳定”版本升级以后旧图布局完全变样差点让文档配图全部失真。从那以后我把渲染环境写进容器镜像任何机器构建结果一致。5. 把 diagram 当代码维护从单张图到图像资产5.1 用“组件化”思想拆图图多了以后你会发现自己重复画了很多相似组件。比如“网关”“鉴权”“日志”几乎出现在每张架构图里。把它们抽到公共模块一张图通过几个引用拼接而成。这样改一次所有引用都会更新。这和写代码抽函数完全一样。但要注意过度抽象如果公共模块参数太多调试成本反而上升。我的经验是公共组件只放稳定不变的默认样式和结构各业务特有的细节留在各自文件里通过覆盖机制调整。举个例子网关这个组件在十张图里都出现但每张图里它的下游并不相同。公共组件只定义形状、颜色和标签下游关系留在业务图中。这样当你决定把“网关”的展示名称改成“API入口”时只改公共组件十张图一起生效。如果不抽公共组件十张图里会有十份手工拷贝必定漏掉几个。组件化不仅省事更重要的是保证同一概念在不同图里长得一样减少认知割裂。5.2 给图写注释、元信息和图例文本图比图片图天然多了“注释”这个表达通道。我习惯在每个节点后加上职责描述例如[订单中心] : 负责订单创建与状态流转 [订单中心] -- 创建 - [订单持久化] : 事务性写入这比单独的一张“组件说明表”更贴近图读图者不用来回切换。还可以在文件头部写三个元信息目标读者、最近确认者、上次审查时间。有位置标注TODO也行保证图能被持续维护。图例也是元信息的一部分放最顶部或右下角线型说明不要太长能区分实线虚线即可。注释还有个独特作用当图要转交给其他人维护时注释就是交接文档。很多图之所以很快腐烂不是因为画错了而是因为当初的设计背景没有留下来后人不敢动。有了注释至少能知道“这里为什么是异步”后人才能判断是否仍然适用。我会在关键节点写上一句“如果此服务拆分需要同步修改XX图”让引用关系变成显式约束。5.3 评审、合并与多版本维护实操我们现在的流程是任何涉及架构变动的PR必须带一张更新后的diagram源码。CI里跑一遍渲染把生成的SVG附到PR评论中评审人直接看图提意见。合并后源码归档老版本随代码仓库天然留存。如果线上系统架构演进要保留至少当前版本和上一版本两张图方便对比。这里最重要的一个心得不要通过“新建副本”维护版本要相信版本管理工具。新建的“最终版2”越多仓库越乱最后没人知道哪张是真的。放弃人类记忆全部交给系统记录。日常修改时我也尽量让一次PR只改一张图的核心信息。如果一张图动了大半评审人会很难看出实质性变化。必要时用脚本生成前后两版图并排预览高亮差异区域。这种“视觉diff”能力是图片工作流根本无法实现的。现在我们把diagram-design做成了团队基础设施的一部分新同学入职第一周就要学会提交一张能通过CI渲染的架构图这不是炫技而是确保所有设计决策都有据可查。我自己踩过很多次坑后才慢慢理解diagram-design 最先服务的其实是绘图者本人。画图的过程逼我把对象和关系一条条写清楚很多模糊不清的设计在写箭头时就会暴露。现在不管多急的方案我都会先花十几分钟写一版图形源码哪怕只有三个节点也比空口讲更扎实。如果你也在被“评审讲不清、文档图过期”困扰建议下次试着把图当代码来设计。工具只是载体真正的价值是让图成为一种可讨论、可追溯、可复用的工程资产。

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

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

免费获取报价 →
↑