很多人觉得画图是个“没有技术含量”的活儿,有手就行。但在大项目里待过的人都知道,一张好的系统结构图比几千行代码更值钱——代码只有能看懂的人才能维护,而一张图可以让一个新同学在十分钟内理解整个业务流转。
diagram-design,说白了就是把“脑子里想明白的东西”变成“别人一眼能看明白的东西”。这件事难不在软件操作,难在画图之前的思考方式。本文不聊某个具体软件的快捷键,也不贴模板,而是把一套从需求整理、信息分层、工具选型到最终维护的完整工作流拆开讲清楚,适合所有需要画技术方案图、架构图、时序图、数据流转图的开发者、架构师和技术文档写作者。
1. diagram-design的本质:不是“画图”,而是“设计”
1.1 图的真正价值:把复杂收敛成决策
我刚带项目那会儿,最喜欢画特别大一张架构图,把所有服务、消息队列、缓存、数据库统统堆在一张A3横版里,连定时任务都画上一个小图标。图是好看的,但你拿给业务方看,他盯了三十秒,问你:这里为什么有两个订单服务?
我答:一个是订单主服务,一个是订单状态机服务。他说:“那这不就是一张图里出现了两个长得差不多的方块吗?用户只看得到一个订单。”
那一课我记到现在。图表的核心价值不是“信息多”,而是“决策快”。一张好的diagram-design,是把复杂的系统收敛成几个关键判断:这套系统有多少个核心模块?请求按什么路径走?边界在哪里?哪些是现有系统,哪些是待建系统?读者看完能立刻知道下一步该同意什么、反对什么,而不是对着图再做一轮阅读理解。
所以设计图的第一步,不是打开任何软件,而是问自己:看这张图的人,他需要做什么决策?他关心的是模块关系,还是调用链,还是部署形态?回答完这个问题,图的边界、粒度和要素就全定下来了。
1.2 一张图的完整生命周期
这里我建议把所有图表工作都拆成四个阶段,缺一个后面都要返工:
- 信息清单阶段:把需求方口头讲的、文档里写的、代码里长的各种各样事实,先全部列出来,不急着连线和摆位置。
- 结构骨架阶段:决定实体有哪些、关系有哪几类、哪些信息砍掉、哪些信息合并,这个阶段产出的是“要素清单+关系清单”。
- 表达细化阶段:决定用什么图元表达节点、用什么线型表达关系、什么信息放图例、什么信息放注释。
- 一致性打磨阶段:统一命名、统一层级、统一配色,把右上角的版本号、日期、作者补上,最后再做一次“新读者测试”。
很多人画图烂,不是因为工具用得差,而是跳过了第一和第二阶段,直接上手拖框连线。拖的时候才发现自己根本没想清楚这个图和那个图之间的关系,画到一半推倒重来,时间全耗在鼠标上了。
1.3 画图员和设计师的区别
说个更直白的判断方法:画图员关心“像不像”,设计师关心“有没有用”。一个方块放左边还是右边,画图员觉得无所谓,设计师会告诉你——左边意味着它是“入口”,右上角意味着它是“重点”,底部意味着它是“支撑设施”,读图的人对位置的潜意识解读比图例更强烈。位置本身就是一种语义。
所以在diagram-design里,布局不只是美学问题,它是信息层级的外化。一个被读者理解成本质上不重要的模块,一旦放在了视觉中心,就会被误读为核心。设计师的工作就是反复调整这个“视觉结构”,直到它和业务结构一致。
2. 手上的工具决定图的层次:主流图表工具的选型逻辑
2.1 文本类工具:Mermaid与PlantUML
先说我最常用的文本类工具。Mermaid是目前在Markdown生态里渗透率最高的,GitHub仓库的README里全是它的图。它的核心逻辑是“用代码写图”,比如下面这个最简单的示例:
graph TD A[用户] --> B[网关] B --> C[订单服务] C --> D[(订单库)]这段代码渲染出来的是一张从用户到网关再到订单服务的流向图。好处是:可版本管理、可diff、可直接嵌进文档或Wiki,改名字、改流向只需要动一行文字,不用拖着鼠标找那条线。坏处是:布局是算法自动排的,想精确控制位置很难,复杂图容易画得“绕”。
PlantUML跟它是同一类思路,强项在时序图和UML类图。它可以用一段很短的描述生成一张标准时序图:
@startuml actor 用户 用户 -> 订单服务: 创建订单 订单服务 -> 库存服务: 扣减库存 库存服务 --> 订单服务: 扣减结果 订单服务 --> 用户: 下单成功 @enduml对于需要大量重复修订的技术文档,文本类工具几乎是唯一解。我在团队里普遍要求方案文档里的图必须用文本类工具,目的只有一个:diff的时候能看出谁改了什么。
2.2 自动布局引擎:Graphviz
如果说Mermaid是轻量级文本图,Graphviz就是重型自动布局引擎。它用DOT语言描述图结构,然后通过布局算法(dot、neato、fdp等)自动决定节点位置。它处理大而复杂的图能力更强,特别是树形结构、状态机、依赖关系图这种有明确结构特征的场景,布局算法排出来比人手拖出来的更均匀、更可读。
不过它也有个让人头疼的点:学习曲线陡,样式定制比较繁琐。你想把节点做成圆角矩形、加个渐变色,都得写样式代码。对大多数日常场景来说,它属于“杀鸡用牛刀”。我只有在画依赖图谱、数据血缘这类节点动辄几十上百的图时,才会搬出Graphviz。
2.3 自由绘制类:Excalidraw与draw.io
也有一些场景,我们需要的不是结构精确,而是“讲清楚概念”——比如在评审会上给业务方画一个流程草稿,或者在设计文档里贴一张“系统间信任关系示意图”。
这类场景我会用Excalidraw。它画出来的手绘风格线条能非常有效地传达“这是草图,我们在讨论思路,不是最终架构”的氛围。视觉上的“未完成感”反而能引导评审者聚焦内容本身,而不是抓着你的线没对齐说半天。这一点很多从业者都低估了,我强烈建议你试一试。
另一款是draw.io(也叫diagrams.net),它走的是“所见即所得”路线,模板库巨大,网络拓扑、云架构、ER图、电路图都有现成的图元,适合交付给客户的正式架构图。缺点是一旦图复杂度上去,维护成本会急剧升高。
2.4 选型建议矩阵
拿我自己的项目经验来看,工具选型没有“最好”,只有“适配”。整理一个很主观的选型建议:
| 场景 | 推荐工具 | 原因 |
|---|---|---|
| 技术方案文档 | Mermaid | 可版本管理、可diff、嵌入Markdown方便 |
| 时序图/类图 | PlantUML | 语义清晰、UML元素完整 |
| 数据血缘/大规模依赖 | Graphviz | 自动布局能力强、大图不绕 |
| 评审会思维碰撞 | Excalidraw | 手绘风格降低讨论压力 |
| 对外交付正式架构图 | draw.io | 模板丰富、样式规范 |
| 图中需要画云资源和网络设备 | draw.io或专业云厂商工具 | 图元标准化程度高 |
还有一个真实的过来人提醒:不要同时让团队三个工具混用。同一个项目的架构图,今天Mermaid明天Excalidraw,最后一定是一堆风格不一致的图躺在文档里没人维护。工具最好由技术负责人统一拍板,风格才能沉淀下来。
3. 让图真正有用的四个原则:从信息分层到视觉重量
3.1 信息分层:先定“哪些不画”
很多人画图失败,不是因为漏了细节,而是因为什么都想画。他的逻辑是:这张图我标清楚了所有服务、所有接口、所有消息类型,读者总该明白了吧?恰恰相反,当信息密度超过读者的处理带宽,他就会放弃阅读。
正确的做法是先定图的主视角,然后狠心砍掉跟主视角无关的信息。你画的是部署架构图,就别在框里写接口名;你画的是业务时序图,就别画数据库表结构。一个元素出现在图里,必须回答“它服务于哪个决策”。回答不了,就删。
这就是“信息分层”——把系统拆到不同抽象层次的图里,每张图只负责一层。子系统的细节放到子图或附录中,主图只留骨架。这跟代码组织是一个道理:类要职责单一,图也要“职责单一”。
3.2 层级对比:字号、线宽与色彩做主次
图里所有元素不可能同等重要,所以你要通过视觉参数建立“主次梯度”。我给自己定过一套很宽松的规则,供参考:
- 核心模块用最粗的边框、最大的字号、灰度最高的填充色。
- 二级模块用细边框、正常字号、浅色填充。
- 外部系统和依赖组件用虚线边框、浅色,拉开与核心的视觉距离。
- 数据存储统一用一种形状(圆柱体),外部系统统一用另一种形状(圆角矩形),这个约定全项目共用。
色彩的运用尤其要克制。选一个主色表示“本方案涉及的核心模块”,选一个中性色表示“既有系统”,再选一个警示色表示“风险点或需要改造的地方”,一共三种颜色够了。颜色越多,读者大脑处理负担越重。你会惊讶地发现,把颜色砍到三种之后,图突然“专业”了起来。
3.3 几何比例:让视觉重量反映业务关系
还有一个容易被忽略的原则:图形的面积大小应该反映业务上的重要程度。核心系统可以用大框,边缘组件用小块。很多人在画图时随手一拖,所有方块等大,最后读者只能靠位置猜测谁重要。
拿一个电商订单流的例子来说:用户、订单服务、支付服务可能是大框;优惠券、积分、消息通知就是小框;那些计划明年才接进来的“智能推荐”模块,应该画成虚线小框并标注“规划中”。这种几何比例本身就是一种信息编码,读者一眼就能看出当前方案的重心在哪里。
如果业务上A模块依赖B模块,但B模块在图上因为历史原因被画得很小很偏,那你应该调整布局,而不是让读者去脑补“这个缩在角落里的小框其实很重要”。图中的位置和大小,必须和你希望传达的业务语义保持一致。
3.4 对齐与一致:细节决定是否“专业”
说个比较扎心的现象:评审会上,你辛辛苦苦画了半天架构图,业务方看完第一句话往往是“这个线怎么歪的”或者“这两个框间距不一样”。人对视觉瑕疵的敏感度远高于对结构错误的敏感度,所以对齐和一致性决定了一张图的“专业下限”。
这部分没有捷径,就是慢工出细活:网格对齐、等间距分布、连线转折点统一、箭头样式统一、文字居中。用代码类工具(Mermaid、PlantUML)时对齐由布局引擎负责,这反而省心。用鼠标拖拽类工具时,务必打开网格吸附,拖完一层就整体对齐一次,不要等画完了再收拾。
还有一个细节:箭头方向。所有关系线最好都明确箭头方向,不要用“两端都有箭头”这种模糊表达。关系是有方向的,A调用B和B调用A是完全不同的语义。一张图里如果大量出现无箭头线段,读者就会怀疑作者自己也没理清关系。
4. 一次完整的架构图设计实战:某电商平台订单履约系统
4.1 需求端给的信息长什么样
理论说再多,不如走一遍完整流程。这是我最近画的某电商平台订单履约系统改造图,从需求到成图大约改了三版,可以拿出来拆解。
技术负责人给的原始信息是一个很典型的“口头需求 + 聊天记录”集合体,原文大意是:我们现在订单流程很乱,下单之后要同时走支付、库存、风控。支付之前先锁库存,锁库存成功才能唤起支付。用户取消订单要释放库存和优惠券。有时候用户支付超时,订单要自动关单。现在想接入一个新的物流服务做发货状态回传。
这些信息能不能直接画图?不能。因为至少有三个关键歧义:库存锁定失败算不算下单失败?支付超时由谁来触发关单?物流回传状态之后是否要更新订单主状态?这些没理清,画出来的图就是“想象图”。
4.2 把口头描述整理成信息清单
第二步是把上一步收集到的信息拆分到四个清单里:
- 实体清单:用户、订单、库存、支付、风控、优惠券、物流、支付网关、MQ(消息队列)、定时任务。
- 关系清单:用户创建订单;订单锁库存;锁定成功则唤起支付;支付前过风控;支付成功通知订单;取消订单释放库存和优惠券;超时未支付触发关单;物流回传状态更新订单。
- 流程起点清单:创建订单、支付回调、取消订单、超时关单、物流回传。
- 边界清单:本轮改造只涉及“订单履约”,不涉及商品中心和搜索推荐。
整理完这张信息清单,图的骨架其实已经很清楚了:五个流程起点,对应五条主链路,而订单服务是唯一的核心枢纽。所有其他服务都通过订单服务发生关系。
4.3 第一版草图的问题与重构
第一版我把“用户创建订单、锁库存、风控、唤起支付”画成了一条主链路,结果整张图的经典问题出现了:我又把时序图的逻辑画成了架构图。一条长链条从左到右拉满,支付在右边,库存服务在左边,网关在最右边,读图的人需要来回扫视。
第二版我换了思路:把订单服务放在正中央,库存、支付、风控、优惠券、物流分布四周,所有连线都指向中央的订单服务。这一版结构是对的,但又有新问题——中央是一个大框,四周也是大框,层级没有拉开,看不出谁是核心。
第三版才理顺:订单服务作为唯一的中心大框,底色最深;库存和支付作为调用频率最高的两个依赖,排在它右侧并用粗线连接;风控、优惠券、物流用细线连接到订单服务底部;MQ和定时任务用虚线画在最底部“支撑层”,不参与主链路视觉竞争。每条关系线上都标注了极简的动词,比如“锁库存”“唤起支付”“回传状态”,而非接口名。
4.4 最终成图的样子与设计取舍
这版图的最终效果,可以用文字描述一下:上半部分是业务主链路,订单框中垂直列出“创建订单、支付回调、取消订单、超时关单、物流回传”五个入口;右侧是支付和库存两个大模块;底部是“基础设施区”,用虚线框住MQ和定时任务;左下角用一个小方块标了“规划中:物流预警”。整张图只有三种颜色,核心方案模块是深蓝色系,既有系统是灰色系,风险点是橙色。
这版的取舍非常清晰:取消了风控服务在视觉上的突出地位,只保留一个标注“风控前置校验”的细线小框,因为它在这次改造里的角色是“校验点”而不是“业务承接方”;把支付和库存放大,是因为所有主链路都要经过它们。图的右上方标注了版本号和日期,左下角留下了作者和评审人的位置。
这样一张图拿去做评审,业务方和研发方向不同但都能在五分钟内理解:流程从哪里开始,哪里是核心,哪些是本次要改的,哪里是未来的。这就算diagram-design到位了。
5. 图表维护心得:避免“画完就废”的几种做法
5.1 图和代码走同一套版本管理
工程师最恨的一件事就是:文档里的图跟代码已经完全对不上了,图是新同事入职时画的,系统已经改了四轮。出现这种问题的根本原因不是懒,而是图没有和代码绑在同一个变更流程里。
我现在坚持一个原则:技术方案里的图,源文件必须入库,跟代码同一个仓库、同一个分支、同一个PR评审。改代码的时候如果涉及模块关系变化,PR里必须同步更新对应图。用Mermaid或PlantUML这类文本工具,这个操作几乎零成本——改几行文字就完事。但用白板截图或draw.io文件的时候,这个流程就会很痛苦,所以这也是我前面推荐文本工具作为团队默认方案的原因之一。
5.2 让图表被评审
“画完就废”的另一个原因,是图从来没被认真看过。我建议每个版本改完图,一定要发出评审邀请或至少让同组人做一次“看图找茬”,尤其是让不是本模块开发的同学帮忙看。因为熟悉业务的人会脑补缺失信息,而新读者就是那张图真正的消费者。他会告诉你:这里我看不懂、那里我以为A调B其实你标的是B调A。这些问题只有他帮你挑得出来。
另一个实操习惯是给每张图写一个极简的“读图说明”,两三行字,写清楚“入口在哪里、核心是哪块、虚线代表什么”。很多人觉得图是自解释的,但自解释不代表零门槛,一个说明往往能大幅减少评审会上“这图我没看懂”的尴尬时刻。
5.3 消费方式决定价值
最后说一个比较反直觉的体会:图的消费方式比图本身重要。同样一张订单履约图,如果只是放在文档里等人点击查看,它的价值可能只有一次评审;但如果你把它拆成两处使用——画成一张“挂在团队Wiki首页的总览图”,再把每个模块单独拆成子图嵌入到具体模块的说明文档里——它的生命周期和价值完全不一样。
所以我在设计diagram-design的时候,会刻意分清哪些图是“总图”,哪些是“子图”。总图追求稳定,很少改动,替团队建立全局认知;子图跟着代码迭代,保证每次变更都有出处。图一旦有了明确归属和消费渠道,维护就不再是一件“想起来才做”的事,而是融入了日常工作节奏。
说到底,diagram-design和写代码一样,都是把复杂的东西结构化,只不过代码面向机器,图面向人。机器的要求是正确,人的要求是“让我少费点脑子”。你画的每一根线,其实都是在替读者省思考时间——这也是为什么我直到今天依然愿意在一张图上花半天:因为它被十个人、一百个人反复看,省下来的时间,足以值回我画图的那几个小时。在下一次动笔之前,不妨先问自己一句:这张图,我要让读者少想什么?