不废话,先聊一个我亲眼见过的场景:一次技术评审会,架构师打开一张画了三天的大图,密密麻麻一百多个节点,线的颜色有八种。会议室坐了二十个人,前十分钟没人说话,后二十分钟全在争论“这两条实线到底是不是同一个链路”。最后主管说了一句“这个图我回去再仔细看”,然后这张图就再也没有人打开过。
这就是大多数技术团队里 diagram-design 的真实处境。图纸本身没有错,错的是我们把“画图”当成了“把代码抄成方块”,而没意识到一张图本质上是沟通过程中的一次压缩和转译。它的好坏不取决于信息量大小,而取决于读者能不能在三秒钟内找到自己想知道的那条路径。今天这篇内容,我就把 diagram-design 从理念、工具、实战到维护的完整方法论一次讲透。不管你是在画系统架构、业务流程图、时序图,还是数据模型,这套思路都通用。它适合开发、架构师、产品经理,也适合任何需要把复杂东西讲清楚的人。
1. 为什么大多数技术图不合格:diagram-design 的核心法则
1.1 一张图的本质是一次“沟通的压缩”
我见过太多人把图当成代码的二维复制品。UML 图要求把每一个类、每一个方法都画出来,流程图恨不得把 if 分支的每个条件都写上去,结果就是图比代码还难读。这不是 diagram-design,这叫“用画图的方式写了一遍代码”。
图存在的意义不是承载信息,而是压缩沟通成本。把你脑子里形成的设计认知,用图形符号快速传递到别人脑子里。这里面最关键的一个词是“别人”。图和代码最大的不同是,代码的最终读者是编译器和少数维护者,图的读者是活生生的人,是产品、测试、新入职的同事、甚至不懂技术的投资人。
所以我在设计每一张图之前,一定会先问自己一个问题:这张图要被谁读?他要从里面获得什么决策依据?如果答案是“给刚入职的后端看调用链路”,那这张图的抽象层级、标注方式、信息密度,和“给部门负责人看系统边界”是完全不同的两回事。
很多图不合格,不是因为画的人技术差,而是因为他根本没搞明白这张图服务的是哪个决策场景。信息压缩的时候该保留什么、该丢弃什么,取舍原则完全由读者决定。你在图里花了三十分钟调出来的大理石纹理背景,对读者理解业务毫无帮助,甚至是有害的视觉污染。
1.2 一张图只能回答一个问题
我在团队里推行过一个很硬的规矩:一张图只回答一个问题。这句话治好了团队里百分之八十的“巨型图综合症”。
什么叫一个问题?比如“用户下单之后,订单状态是怎么流转的?”这是一个问题。“我们的系统包括哪些模块,模块之间怎么通信,通信失败了怎么办,数据存在哪里,日志怎么收集……”这不是一个问题,这是一篇文档。你要画的是架构全景图、部署图、时序图、流程图,它们是不同类型的图,不该被揉在一起。
有人会反驳说,系统全景图就是要展示所有模块啊。对,全景图可以展示所有模块,但它的核心问题是“系统由哪些部分组成、边界在哪里”,而不是“订单状态怎么流转”。每一张图都应该有一个明确的主题句,就像文章的主旨句。如果这张图讲了一件事之后还有精力讲第二件事,那就让它闭嘴,第二件事单独出一张图,然后建立引用关系。
这样做的代价是图的数量变多,但每个图都可以做得很简单、很干净;收益是极低的认知负担。你可以把图当文章来理解——一张图一个段落,多个图组成一节,节点之间的连线就是句子的谓语。diagram-design 的最高境界不是一张图画得多么惊艳,而是这套图的组合能像一本好书一样,带着读者一层层往下走。
1.3 三个层级:草图、工程图、展览图
我把 diagram-design 的产出物分成三个层级,不同阶段对精细度的要求完全不同。
第一层叫草图,或者叫白板图。这是头脑风暴、需求预沟通时用的,目的就是快速对齐思路,随手画个框、拉几条线就够了,不需要任何工具规范。草图画完之后的价值不在那张纸或那块白板上,而在讨论过程中达成的共识。画完拍照发群里,这件事就算完成了。
第二层叫工程图。这是要被写进设计文档、用于方案评审的图。到了这个层级,图必须遵守一致性规则:节点类型不能乱用,颜色不能随便给,文字标注得清晰,连线的语义要统一。工程图的读者是团队成员,他们要基于这张图展开技术讨论,所以图的准确性比美观重要。但准确性不意味着可以牺牲可读性——一张图如果让人一眼看不下去,再准确也没人看。
第三层叫展览图。这是用于对外汇报、技术博客、开源项目 README 的图,美观度被提到很高的优先级。展览图的本质是“产品”,读者会用浏览而不是阅读的方式去看它,所以你必须在第一眼就抓住他们的注意力。配色要克制,布局要均衡,关键路径要高亮。网上那些收藏量很高的架构图,基本都是展览图级别的作品。
搞清楚你眼下要画的图属于哪个层级,比打开哪个工具重要得多。很多人一上来就对着 draw.io 的模板库陷入选择困难,其实是把“画草图”的时间硬生生拖成了“画展览图”的节奏,最后两头都不讨好。
2. 工具选型:代码化绘图与拖拽绘图的取舍
2.1 主流的四个流派,选型前先看懂差别
diagram-design 的工具生态看起来乱,其实可以归成几个流派,每个流派的核心逻辑和适用场景都不一样。
- 代码化 DSL 类:Mermaid、PlantUML、D2、Graphviz、Structurizr DSL。核心逻辑是“用文本描述结构,工具负责渲染成图”。
- 拖拽白板类:draw.io(现在叫 diagrams.net)、Excalidraw、Figma(含 FigJam)、Visio。核心逻辑是“所见即所得,自由摆放形状”。
- 专业建模类:Enterprise Architect、Visual Paradigm、StarUML。核心逻辑是“围绕某种建模标准(比如 UML、BPMN)提供完整的工程规范”。
- 数据可视化类:ECharts、D3、Grafana、Tableau。这一类严格说偏向数据图表,但做架构看板时也会用到,所以顺带列一下。
在系统设计这个语境下,我觉得最值得认真对比的是前两类。拖拽绘图的好处是自由,画出来的图天生就符合人的空间直觉,布局可以手工调得很漂亮;坏处是难以版本化、难以审查、难以复用,图上改了一个字,整张图的修改记录都混在一起。
代码化绘图正好反过来,它牺牲了部分排版自由度,换来的是文件化、可 diff、可复用、可自动化校验。还有一个很多人没意识到的好处:因为图是文本生成的,你可以在任何时候重新渲染出一个统一风格的版本,而不会出现“每个人手里都有一份改得五花八门的架构图”的情况。
2.2 我的工具组合:分场景使用,别指望一把锤子打天下
后台经常有人私信问我“能不能只推荐一个画图工具”,我的答案一直是可以,但前提是你愿意承担它在某些场景下的短板。我自己目前的组合是分场景的,分享一下给大家参考。
团队头脑风暴或者快速记录想法,用 Excalidraw。它的手绘风格天生就带有一种“这还不是最终结论”的暗示,能够有效降低讨论阻力。正式的设计文档和架构评审,优先用代码化方案。写代码文档的时候用 Structurizr DSL 描述容器和组件关系,它天然支持 C4 模型,改起来也方便。遇到需要精细控制布局的场景(比如对外发布会用到的部署拓扑图),我会用 draw.io 手工编排。它虽然是拖拽工具,但胜在免费、不锁死格式,而且可以导出干净的 SVG。
这套组合的核心思想不是“这个工具最强大”,而是“每个工具都在它最合适的位置上”。如果只能留一个工具给刚入门的团队,我会建议从代码化绘图开始。原因是它的产出物更容易沉淀和演进,而 diagram-design 这件事,长期主义比短期手速重要得多。
2.3 为什么代码化绘图值得认真对待
如果说我这几年的 diagram-design 经历里有什么最值得分享的认知,那就是:图的维护成本,往往比图的创作成本高一个数量级。
拖拽画图最大的坑不是画得慢,而是画完之后没人维护。半年之后系统迭代了三个版本,架构图还停留在半年前,新同事照着图去理解系统,结果图里一半的模块已经改名了。这种“过期图”比没有图更可怕,因为图给人的信任感比文字强太多,一个错误图例带着整支团队往错误的方向理解系统。
代码化绘图天然对抗这个问题。因为图源文件是文本,你可以把它和代码放到同一个仓库里,在同一个 PR 里修改代码和对应架构图。代码评审的时候,图也跟着被 diff,有没有同步更新一目了然。Mermaid 这样的工具已经支持在 Markdown 里直接嵌入渲染,PlantUML 的文本格式也非常接近伪代码,团队上手成本不高。
我把“图跟代码一起进版本库、一起走评审流程”这条原则当成了团队铁律之后,架构图的准确率大幅提升。更意外的是,大家愿意改图了。以前改图要在画图软件里扒拉半天,现在改一行文本提交上去就行,动力完全不一样。
3. 实战:从零设计一张系统架构图
3.1 第一步:明确读者和核心问题
现在我们把目光放到一张具体的系统架构图上,完整走一遍实操过程。假设我们要给一个电商系统的下单链路画一张容器层架构图,它服务于“技术方案评审”,读者是团队内部开发同学。
评审会上的架构图,核心要回答的问题不是“为什么选用 MongoDB”这种细枝末节,而是“用户从发起下单到订单生成,中间经过哪些系统容器,各自的职责边界是什么,关键依赖关系是怎样的”。所以这张图的主体元素是容器,也就是可独立部署的服务、数据库、消息队列这些运行单元,而不是具体到类级别的代码细节。
想清楚这一点之后,你的信息采集清单就清晰了。梳理出参与下单链路的容器名称、每个容器的核心职责、容器之间的调用关系、外部依赖的范围,然后才开始画图。很多人的错误做法是先开画再想,画到一半发现“哦对还有这个服务”,于是在图上临时追加节点,最后布局越来越乱。diagram-design 的正确顺序一定是先想明白再上手。
3.2 用 C4 模型做分层:从 Context 逐层收敛
热身环节,先把 C4 模型搬出来。C4 是 Simon Brown 提出的一种建筑学灵感的分层图示方法,四个 C 分别是 Context(系统上下文)、Container(容器)、Component(组件)和 Code(代码)。绝大多数系统架构图只需要用到前两层,但哪怕只用两层,这套思考方式也足够帮你理清粒度。
Context 层解决“系统在环境中处于什么位置”的问题。画法极简:一个系统框(我们的电商系统),几个外部角色和系统(用户、支付渠道、物流平台),以及几条关键依赖连线。这一层的价值是让所有人在同一个大图景里对齐,避免一上来就钻进某个服务出不来。
Container 层解决“系统由哪些可独立部署的单元组成”的问题。以我们的下单链路为例,文字结构大致是这样的:
- 浏览器端用户
- 商城前端网关(负责鉴权、限流、路由)
- 交易中心(负责下单主流程、订单状态机)
- 商品服务(负责库存校验与查询)
- 支付服务(负责拉起支付、回调处理)
- 订单数据库(MySQL,主数据存储)
- 消息队列(Kafka,用于订单事件分发)
- 外部依赖(微信支付、物流开放平台)
从 Context 到 Container 的过程,是一次“逐步放大”的过程。每一步只新增一个层级的细节,不给读者填无关信息。这个经验特别适合给新手:如果你画图的时候觉得很难决定保留哪些细节,说明你还没有完成从 Context 到 Container 的粒度切换。
3.3 形状、颜色与字体:建立统一的视觉编码
画图的“艺术性”其实是一种编码能力。形状、颜色、线型,都是在向读者传递语义,和编码一样需要一致性和共识。
形状语义我建议团队内固定下来。人的角色用圆形,系统/服务用矩形,数据存储用圆柱体,外部依赖用带外边框的矩形(虚线框也常见)。不同类型的图里规则可以微调,但同一张图内绝对不能混用。我见过有人用两种不同都矩形表示“内部服务”和“外部依赖”,只是颜色深浅不同,结果评审会上三成时间都在确认图例。这种误差在 diagram-design 里属于低级事故。
颜色的第一原则是“少即是多”。整体色系控制在三个以内,最多加一个警示色。用蓝色系表示核心业务模块,灰色表示基础依赖,橙色表示第三方服务,这个习惯我延用了很多年。高亮某条关键调用链时,把高亮路径的线宽加粗、颜色加深,把其他连线统一降到浅灰,读者的视线会第一时间锁定到你想要强调的路径上。
字体和字号也别随意。标题用 16 到 20 像素,节点名称 14 到 16 像素,说明文字 12 到 13 像素,层级分明就够了。很多图显得“业余”,其实不是内容不行,而是字号层级混乱,视觉权重失衡。
3.4 布局排版的那些细节:交叉、方向与呼吸感
哪怕你上面的语义编码全做对了,布局上一团糟,图还是会让人一眼放弃。我给你几个反复踩坑总结出来的具体原则。
第一,连线交叉要降到最低限度。交叉线是阅读中断最直接的元凶,处理办法是重新排序节点,常见的容器排列方向可以从上到下,也可能是从左到右。在代码化绘图里这个工作很令人头疼,拖拽工具里手动调整会容易很多。第二,矢量的流向要一致。比如用户请求从左侧进来,那么整条链路尽量都保持从左到右推进,反转流向的连线要有极强的理由。第三,留白要足够。节点之间不要贴得太紧,紧凑的排版也许省空间,但阅读节奏会被密集的边界线打乱。第四,主链路放在图的中央或主轴线上,辅助依赖放在边缘。
这些布局工作没有高深的理论,但会极大影响图的“专业感”。我的习惯是画完之后退到一米外,眯着眼睛看一秒钟——如果一眼看到底,这张图大概率是合格的;如果要凑近了才能知道主链路在哪,哪怕再漂亮也要重排。
4. 全局视角:让图示成为团队资产
4.1 图中一致性维护:图也是要“治理”的
diagram-design 做到后面,真正的难点不是画某一张图,而是如何让几十张图长期保持可用。太多团队的第一张架构图画得惊为天人,半年之后沦为废纸,核心原因是图的维护没有纳入治理体系。
图的治理和代码治理是同构的。谁负责、多久审一次、变化了怎么更新,这些都要有归属。建议每个关键子系统指定一个“图示负责人”,一般是该系统的技术主力。这不是给他增加无意义的负担,而是把“讲清楚系统”作为系统开发的一部分。代码改了,图就要改;图改了,代码也要能对应上。这两者没有严格的先后,但必须联动。
你如果遇到“图一旦画完就再也无人更新”的情况,多半不是团队懒,而是没有设置触发更新的机制。上线了一个新容器、重构了一个模块,这些事情发生时,负责的工程师脑子里应该有一个条件反射:文档里的那张图要不要同步?把图的更新放进 Definition of Done,运行一个迭代之后再回头看,图就不会烂得那么快。
4.2 把图放进代码仓库:一个可复用的工作流
分享一下我现在团队里运行的 diagram-design 工作流,你可以根据自己的实际情况调整。
在代码仓库的一级目录下新建 docs/architecture,按子系统建子目录,每个子系统目录里放着它的架构图源文件、说明文档、变更记录。代码化绘图是这里的核心,所有架构图都用文本形式定义,统一放在这个目录下。重要设计评审前,图源文件和设计文档一起进入 MR/PR,评审人可以在 diff 中清晰看到图的变更内容,不是像素级对比,而是文本语义级的对比。
为了让这些文本图在文档站里面也能直接渲染,我在 CI 里加了一个步骤,自动把图源文件渲染成 SVG 并发布到内部文档平台。这样一来,仓库里的源文件是唯一事实源,文档站里的图只是渲染产物。流程跑通之后,团队再也没有发生过“张三的架构图和李四的理解不一样”这种问题。
4.3 图的演进与弃用机制
系统演进的过程中,旧图会失去价值,这时不要硬维护。我这里有一条原则:图与实际系统不一致时,赶紧处理,先做标记,再决定走向。如果是一处小改动,直接更新源文件;如果是结构性大改动,旧图就会误导人,把它移动到 archive 目录里,标注“已弃用”,写明弃用原因和替代图地址。
很多团队不舍得弃用旧图,觉得“以后可能还用得上”。但旧图留在原处会持续制造混乱,更明智的做法是把它们隔离到 archive 目录,让活跃文档始终干净。新成员入职学习时,只看活跃文档就够了,不会陷入“这份图半年前就过时了”的谜题里。
这个机制看着很简单,实际执行起来需要团队共识。我在推行时没有直接用规章制度压人,而是先在组会上展示了三张过期图和一张最新图放在一起的效果,让大家自己判断哪些该保留哪些该移走。共识达成之后再落地,阻力会小很多。
5. 常见问题与排查技巧实录
5.1 一张烂图的五个“典型症状”
我把这些年评审图和修复图中遇到的高频问题整理成了一张排查表,供大家对照参考。
| 症状 | 典型表现 | 根因 | 修复思路 |
|---|---|---|---|
| 巨型图综合症 | 节点超过40个,一张图想覆盖全部系统 | 没有定义图的核心问题 | 拆分成多张主题图,增加引用关系 |
| 有箱子没有流 | 大量节点排列整齐,连线很少 | 只画了静态结构,没表达交互 | 补关键调用路径,删无语义连线 |
| 彩虹色轰炸 | 颜色超过6种,还带渐变和背景色 | 把颜色当装饰,而不是编码信息 | 收敛到3色以内,突出一条主链路 |
| 交叉线九连环 | 连线绕来绕去,阅读断裂 | 布局前没有规划主方向 | 重新排列容器顺序,主线优先无交叉 |
| 图例不等于内容 | 图例画得很专业,但实际节点乱用形状 | 制作时未遵守自己定的规范 | 把规则固化到工具模板或 DSL 中 |
这张表里每一项我都亲手处理过。印象最深的是“巨型图综合症”,一位同事把公司整个技术架构画在一张 A0 大图里,开源工具渲染出来足足有两米宽。我让他把它拆成“系统上下文”“核心链路”和“部署拓扑”三张图,结果每张图变得清爽又易懂。拆完之后他自己也感慨,之前的图更像在陈列,而不是在沟通。
5.2 拿到一张烂图,怎么一步步“救活”它
假设你现在接手了一张前任留下的复杂架构图,第一眼看不懂,怎么让它恢复价值?我给一个四分法流程。
第一步,问目标。翻设计文档或者问负责人,确认这张图原本要回答什么问题。如果没人能说清,说明这张图从诞生起就缺乏价值锚点,不值得修复,直接归档处理。第二步,做盘点。把图里出现的所有概念列出来,分到“核心元素”和“边缘元素”两组。核心元素指那些出现在主链路必须经过的节点,边缘元素是辅助说明。第三步,重画主干。只保留核心元素,按调用顺序从左到右或从上到下排列,连上主线,这一版大概只花十分钟,但阅读性已经是原图的数倍。第四步,逐层加回边缘元素。每加一个节点都要问自己“没有它,读者会误解什么吗?”想不清楚就不加。
救图的过程其实和重构代码很像。先明确行为(图的服务对象),再抽主干(语义骨架),最后再决定哪些细节值得保留。如果你觉得这个流程做完之后图依然很难看,不要怀疑自己,问题很可能出在最初的信息组织方式上,而不是你的画图技巧。
5.3 代码化绘图常见疑难杂症
代码化绘图虽然高效,踩坑的地方也不少,我把自己在 Mermaid 和 Structurizr 里遇到的典型问题列一下。
Mermaid 时序图消息文本太长时,渲染出来的图会特别宽,阅读体验极差。我的办法是给消息文本建“别名”。先用简短的代号表示消息,再在消息列表下方单独注释拓展完整内容,图面能清爽很多。还有 Mermaid 里布局引擎在不同平台上的渲染结果可能不一样,本地预览和文档站渲染的间距略有差异。这个不用强行对齐,只要方向一致就足够清晰了。
Structurizr 的 DSL 优点是准确性极高,缺点同样明显:上手有门槛。团队第一次用的时候,不少人不知道 dynamic view 和 component view 的区别,画出来的图要么太粗要么太细。我建议刚开始学的时候不要贪多,先把 system context 和 container 两张图画顺,用一段时间之后再引入 component 层。DSL 文本里每行缩进错了都会导致的关系崩掉,所以建议编辑器里开两个面板,左侧 DSL,右侧实时预览,能在第一时间发现层级错误。
抽到这种工具的另一个常见问题,是中文渲染时字体偏小或显示不全。目前比较稳妥的做法是在配置里显式指定思源黑体或微软雅黑,渲染出来之后人工抽查一下边界情况。
写在最后:diagram-design 更看重“养成”而不是“爆发”
聊了这么多,如果你只记住一句话,我建议记住这句:diagram-design 不是画图天赋,也不是软件操作技能,它是你对系统的认知能不能被有效传递给别人的能力。
我自己带过很多新人,一开始他们都迷信画图工具里那些华丽的模板和图标库,后来都老老实实回到“先想清楚要表达什么”这条路上来。图是思考的外化,思考不清楚的时候,任何工具都救不了你。
最后再分享一个小技巧:每个季度或者每个大版本结束后,挑一张团队里最核心的架构图,花半小时重新审视一遍——删除已经不在的节点,补充新引入的依赖,调整一下已被业务变化的边界。这个动作看着很小,但它能保证你最常用的那张图永远保持新鲜,而且处理起来比你想的轻松很多,因为用代码化绘图改图,往往就是删三行加两行的事。