我见过太多架构图,从配色到布局都挑不出毛病,但看完之后你依然说不清楚这个系统到底是怎么跑起来的。这其实是diagram-design里最常见的问题:好看,但没有信息量。图不是越复杂越好,也不是越简约越好,而是要让看的人在最短时间内得到它该得到的答案。这篇东西是我在好几个项目里反复折腾之后沉淀下来的画图方法论,不聊天花乱坠的艺术审美,只讲技术人怎么把一张图从“能看”做到“能直接用”,适合写技术方案、做设计评审、整理知识库的开发者和文档工程师。
1. 判断“要不要画图”:一张图从立项到交付的生命周期
很多人一上来就打开工具开始拖框框,这是画图失败的第一步。画图本身是有成本的,维护图的成本更高,所以先想清楚这张图存在的理由。
1.1 图的本质是压缩信息,不是展示全部细节
一张好的设计图,本质是“压缩”过的信息模型。你把系统里的核心组件、关键链路、主要依赖关系用一种视觉语言表达出来,目的是让读者在几十秒内建立对这个系统的心智模型。
如果一张图需要看五分钟才能看懂,那它已经失败了。因为它把文字文档做的事又用图形做了一遍,还没有文字表达得准确。画图前先问自己:这段关系用文字说不清楚吗?如果能说清楚,那图就是多余的。
我通常用两个指标判断一张图是否合格:一个是“扫读时间”,读者扫一眼能抓住主干;另一个是“理解深度”,读者深入看时能找到细节的入口。这两个指标经常是矛盾的,所以要在画图之前就决定,这张图是给“扫读”用的,还是给“细看”用的,鱼和熊掌不能兼得。
1.2 “四问法”确定图的边界
在动手前,我用四个问题给图做定位,答完这四个问题,画图的方向基本就定了。
第一问:这张图的观众是谁?不看代码的业务方、刚入职的同事,还是需要评审的资深架构师?观众的背景直接决定抽象层级。给业务方看,就少画中间件细节;给架构师看,就多标注协议和部署边界。
第二问:这张图服务于什么决策?画图通常是为了回答某类问题:系统是否具备高可用?数据流向是否清晰?模块划分是否合理?你的图要能让看的人直接得出这个决策,否则就没有时效性。
第三问:这张图的保质期有多长?一次性讲解用的图,画得糙一点没关系,重点是把当前的信息讲清楚;要长期维护在文档库里的图,就必须考虑可修改性、可版本管理,甚至可自动校验。
第四问:图的边界在哪里?系统边界、模块边界、数据边界,一张图不可能画出所有内容,画多了信息就糊。通常一张图只表达一个主题,多个主题就拆成多张图。
1.3 图形语言的选择:架构图、流程图、时序图,别混着用
确定要画图之后,还要选对图形语言。这个环节很多人不重视,经常把流程图画成架构图,或者把架构图画成部署图,四不像的东西看着热闹,实际信息传达效率极低。
架构图表达的是空间关系:什么组件在什么位置、谁依赖谁、数据经过哪些节点。这类图的核心是“拓扑结构”。流程图表达的是时间关系:某个流程从开始到结束经过哪些步骤,分支怎么走。它的核心是“状态流转”。时序图表达的是交互关系:多个对象之间按时间顺序的消息传递。它的核心是“调用顺序”。
有一类图我特别喜欢,叫“数据流图”,它不画具体的组件拓扑,而是画数据从源头到消费者的完整路径,中间标注存储在哪、转换在哪、丢失风险在哪。排查数据问题时,这类图比架构图好用十倍。
2. 工具选型:从笔尖到像素的距离
工具选错,画图过程会非常痛苦。我见过太多人用设计软件画架构图,画完自己都懒得改,因为调整一个框的位置要拖动好几个关联对象。工具的定位决定了图的维护成本。
2.1 三类工具的定位差异
按使用方式,主流画图工具基本可以分三类:自由绘制型、结构化文本型、精细设计型。
自由绘制型的代表是各类在线白板和手绘工具,优势是上手极快、开会时能实时协作,适合头脑风暴和临时讲解,但它产出的图基本不具备可维护性,因为位置信息都是手工拖出来的,改动成本高。结构化文本型工具,比如PlantUML这类,通过描述语言自动生成图,优势是可以用文本做版本管理、支持代码审查式协作,修改成本极低,适合长期维护的技术文档。精细设计型工具的优点是视觉表现力强、模板丰富,适合做对外展示的PPT图,但维护成本最高,每次改动都要手动调整布局。
我给三类工具做了个简单对照:
| 工具类型 | 上手速度 | 可维护性 | 版本管理 | 适合场景 |
|---|---|---|---|---|
| 自由绘制型 | 快 | 差 | 不支持 | 临时讨论、头脑风暴 |
| 结构化文本型 | 中 | 优秀 | 天然支持 | 长期文档、架构评审 |
| 精细设计型 | 中慢 | 中低 | 文件管理 | 对外展示、PPT配图 |
2.2 我的默认选择:能文本化就不要拖拽
现在的技术文档和代码仓库紧密捆绑,图如果不能用文本描述,就很难跟着代码一起评审和演进。
我在多数项目里的默认方案是:使用基于文本描述生成图的方式。把图定义写在一个文本文件里,放进代码仓库,随代码一起走。组件、连接线、分组、颜色都通过文本控制,这带来的最大好处是:改图可以用提交记录追踪,评审时可以逐行评论,再也不用问“这张图是谁改的?为什么把那个框删了?”
有人觉得用文本画图记不住语法,我的经验是:只要把常用片段沉淀成模板,画图速度比你想象得快。而且文本方式天然鼓励模块化,你可以把公共组件定义抽到公共文件中复用,后期维护非常灵活。
2.3 “图源文件也是代码”:把图纳入工程实践
把图的源文件当成代码,意味着三件事:第一,进版本仓库,任何人可以通过提交历史看到图的演进过程;第二,进评审流程,画的图要像代码一样被同行review,布局可以随意,但信息不能错;第三,进自动化检查,语法错误、孤立节点、未连接的组件,都可以通过脚本在提交时自动检测。
有一次我在项目里处理某微服务系统的架构图,因为图源文件是文本格式,我甚至在CI流程里加了自动化检查,发现连接线指向不存在的组件就直接构建失败。跑了一周就抓出三次手误,这在传统绘图工具里是不可想象的。把图升级为工程资产,带来的收益远不止画图本身。
3. 画好一张架构图的七步法:每步的关键决策点
下面进入核心实操环节。我总结了从零画好一张架构图的七个步骤,这不是什么官方标准,是我在多个项目里反复试错后沉淀下来的流程。
3.1 第一步:从组件清单开始,而不是从画布开始
绝大多数人画图失败,是因为一上来就打开空白画布,边画边想组件该放哪。正确做法是先在文本里列出组件清单。
组件清单的格式很简单:组件名称、一句话职责说明、所属层级/分组。这张清单决定了图的完整性和边界。组件漏了,图画得再好看,评审时也会被一针见血地指出“这里少了一个服务”。我一般会用至少十分钟做这一步,把代码目录、配置项、部署文件里能看到的服务和依赖全部列出来,宁可多列再删,也不要画到一半回去翻代码。
3.2 第二步:确定主分层与顶层抽象
组件列完之后,要先做“抽象”:哪些组件是核心业务,哪些是基础设施,哪些是外部依赖?分层的逻辑有很多种,可以按技术层级分、按业务域分、按部署边界分。关键是选一种能让观众最快理解系统的划分方式。
我在大多数技术方案里用的是“下三层”结构:接入层、业务层、数据层,外部依赖单独划一个区域。顶层抽象要控制在五到七个分组内,人的工作记忆容量大约就是七个左右的块,超过这个数量,看图的人就开始感觉吃力了。
3.3 第三步:只保留关键连接线
组件和分组确定后,先不急着连线。先想清楚每一根连线存在的理由:它是调用关系、数据流,还是部署依赖?
新手画图最大的问题是不舍得删线:服务A调了服务B,就把它们连起来,结果整个图变成一团毛线球,谁也看不懂。我的经验是:每个组件最多保留三到五根关键连接线,其他调用关系用文字或者序号标注,或者干脆砍掉。
连线不是越全越好,因为连接线的集合像是在描述“一切皆有可能”,而不是在描述关键路径。架构图的重点应该是让读者快速识别出最常用的主链路和最关键的依赖关系。
3.4 第四步:标注非对称信息
一张只画了框和线的架构图,只是“关系图”,还不是“架构图”。真正的架构信息往往体现在非对称信息里:协议类型、调用方向、数据量级、同步还是异步。
比如同样是连一条线,标注“HTTP/JSON调用”和标注“异步MQ消息,平均每秒2万条”传达的信息密度完全不同。我画图时会专门用注释或标签把这类信息标注在关键连接线上,每张图最多标注三到四处高价值的非对称信息,多了视觉会重,读者会失去焦点。
这里也牵扯到一个重要原则:图中需要标注异常路径。容错、重试、熔断、降级这些内容,很多人只在文字描述里写,图上一律不画。但评审架构时,重点看的恰恰是异常路径,正常调用链没什么好看的,挂了之后怎么办才是架构设计的精髓。
3.5 第五步:降低视觉噪音
视觉噪音是指那些不影响信息传达、但会分散注意力的元素。常见的噪音源包括:无意义的装饰性阴影、过度鲜艳的配色、倾斜或旋转的文字、嵌套过深的容器。
处理这些噪音时,我给自己定了一个“空八秒”策略:画完主体后,我盯着图看八秒钟,看哪个元素最先抢走注意力。如果抢走注意力的不是核心组件,而是某个装饰元素,就把它干掉。每一根线、每一个标签、每一块颜色,如果不能解释自己存在的理由,就应该被删除。
3.6 第六步:用“30秒测试”验收
图初步成型后,我会做一次“30秒测试”:把图给一个不了解这个系统的人看30秒,然后让他告诉我,他记住了什么。
如果对方能准确说出“这是一个三层架构,用户请求先进网关,然后到业务服务,最后落到数据库”,说明这张图的主干清晰;如果对方只记得“颜色很漂亮”或“方框很多”,说明图还需要大改。这个测试很简单,但是在真实项目里非常有效,因为它逼着你从读者的视角反过来审视自己的图。
3.7 第七步:追踪率和变更日志
最后一步是容易被忽略的长期维护工作。不管用什么工具画的图,都要想清楚它将来怎么更新。
我习惯在图的源文件顶部维护一个变更日志块,记录日期、变更人和变更原因。这不是形式主义,而是因为图有一个天然缺陷:它看起来越正式,别人越容易相信它,一旦图和实际系统有偏差,它就会变成误导人的陷阱。维护一个简单的日志,至少能让后来人先看变更历史再读图。
4. 布局、配色和字号的隐性规则
这一节要聊的是图的美学判断。声音听起来像是“审美”很玄,但技术图里的美学其实有一堆可以量化的规则。
4.1 布局的“阅读惯性”:从左上到右下
人的阅读习惯是从左到右、从上到下。所以一张架构图应该顺着这个方向安排信息层级:核心入口放在左上角区域,数据最终出口放在右下角区域,主数据流尽量顺着对角线方向走。
举个例子,如果你画一个数据链路图,数据从左上角的接入端进入,流经中间的处理节点,最后汇聚到右下角的数据存储,读者即使不看箭头,也很容易理解大方向。反之,如果你把左下方当一个中转跳板,再绕回到右上区域,读者会直觉反应“这个系统怎么乱糟糟的”。
技术图要遵守的一个朴素原理是“方向一致性”:同一张图中,主要的流线要么统一向右,要么统一向下,不要出现一半向右、一半向左、还有一条弧线绕一圈的情况,这种图无论画得多整齐,读起来都会觉得别扭。
4.2 配色:用色不超过三种语义
配色是视觉噪音最大的来源之一。我见过一些图,恨不得每个组件一种颜色,看起来像掉了彩色打印机的墨盒。技术图不是海报,配色要服务于信息分类。
我的规则是:整张图最多使用三种有语义的颜色,比如业务组件用一种,基础设施用一种,外部系统用一种。灰色用于中性容器和背景。强调色只能用于需要引人注意的关键路径,比如一条异步消息的失败重试链路,用红色系突出。其余组件一律使用默认色或者统一的浅色系。
这套规则带来一个额外好处:未来看图的人能快速识别分类,而不用去对照图例。如果颜色本身不能帮助理解,那颜色就纯粹是干扰。
4.3 字号与间距:最小可读原则
字号不能太小。很多图用导出图片再放大看的模式,忽略了屏幕阅读和打印阅读的差异。我的经验是:画布默认字号底下,正文字号不得小于某个可读阈值(一般建议不小于 12px 当量),标签字号可以更小一点,但不允许低于正文的一半。
间距也是信息设计的一部分。组件之间的间距要体现关系强弱的层次:强关联的组件间距小,弱关联或无关的组件间距大。间距均匀会让图看起来“呆板”,真正的专业感来自有节奏的疏密变化。用一句话概括:密的地方表明它们是一个整体,疏的地方说明它们之间存在边界。
4.4 深色/浅色适配:导出前必做检查
这个坑我踩过很多次。在浅色背景下精心调配的颜色,一放到深色演示文稿里就全部失去了层次感,浅色的边框线直接消失,浅灰的底色变成一团黑。
经验教训是:在导出之前,至少检查两种背景下的显示效果。如果你的图经常要嵌入不同风格的文档,就尽量采用“底色透明或白色、用边框区分边界”的策略,而不是依赖浅色填充来区分区域。曾经我在某跨平台系统的设计方案里画了一张分层架构图,浅色下看起来清爽干净,放到深色主题的评审PPT里简直惨不忍睹,后来专门调整成全套颜色,折腾了两个小时。那次之后,我给自己定了一条规则:画布背景永远使用浅色系,但主要区域的区分必须依赖边框线而不是填充色,这样在深色背景下依然有识别度。
5. 我踩过最深的坑:版本漂移与“图给谁看”的错位
画了几年图之后,让我印象最深刻的往往不是画得多漂亮的图,而是那些在实际项目里“翻车”的图。讲两个最有代表性的问题,希望你绕开。
5.1 图漂移:代码改了三轮,图还在原点
“图漂移”指图和代码不一致。这个问题几乎是所有长期维护的技术文档的死穴。代码每一周都在演进,但图常常因为没人更新,几个月后还停留在旧版本。
有一次在某跨平台系统项目里,我用结构化文本工具画了一张模块依赖图,当时很得意,分层清楚,指向明确。结果三个月后,代码已经迭代了四五轮,几个核心模块被拆分重组,而那张图还安安静静地躺在文档目录里。新来的同事照着图找模块,找了半天没找到,跑来问我,我才意识到图已经漂移得面目全非。
解决图漂移,靠自觉是不够的。我现在会做两件事:一是在图源文件里写一个“经验值”标注,记录这张图最后一次核对时的代码提交号,信息一目了然;二是把图的更新逻辑绑定到日常开发流程里,任何模块拆分或接口变更的任务,都要附带更新对应图的检查项。人肉记忆不可靠,流程绑定才有用。
5.2 “图给评审专家看”还是“给开发看”:两种受众的反向要求
同一个系统,给评审专家看的图和给一线开发看的图,画法完全相反。
给评审专家看的图,要突出系统的决策性信息:容错设计、扩展性、边界划分、风险点。组件可以画得粗一点,但关键的架构决策一定要在图上看得见。给一线开发看的图,要突出可执行信息:模块路径、接口位置、运行环境,务必要详细,能让开发照着图直接定位到代码目录。
这两类图的冲突点在于抽象层级:评审图追求“大局”,开发图追求“可操作”。一张图同时满足两种需求,结果往往是两头不讨好。我现在倾向于分开出图:评审备一套高层架构图,代码库维护一套详细模块图,两套图之间保持同一个组件命名体系,这样不会产生歧义。
5.3 把图放进 README 之前要做的三个检查
很多项目的 README 都放一张架构图当门面,但放之前,我建议至少做三个检查。
第一,检查信息和代码是否一致,最好由最近改过代码的人来核对;第二,检查导出格式是否清晰,README 里通常使用图片格式,要确认放大后不模糊,文字还能看得清,我一般会导一份 SVG 一份 PNG,SVG 用于在线查看,PNG 用于快速加载;第三,检查新读者能否自主理解,让一个没参与项目的人看图并复述,如果他复述出来的内容和你预期的不一致,那说明图的表达有问题。
这三个检查做完再放 README,才能避免“门面图”变成“误导图”。
6. 进阶思路:让图具备“可维护性”的设计模式
到这里,基础画图方法论已经覆盖得差不多了。再聊几个让我受益很深的进阶实践,这些经验在长期维护的大型系统里价值极高。
6.1 模块化组合:用小图拼大图
一张大图承载的信息量一旦超过七个分组,读者的理解成本就会骤增。与其硬塞,不如拆图。
我现在处理复杂系统时,采用“总图 + 子图”的组合模式:总图只画顶层容器和容器之间的关键调用关系,每个容器内部对应单独一张子图,子图里再画模块级别的依赖和数据流。这样每个层级的信息都控制在可理解范围内。
这个模式还带来了一个附加好处:子图可以独立更新。某个业务模块迭代了,只需要更新对应的子图,总图往往不受影响。总图和子图之间通过命名前缀关联,比如“订单域-创建订单时序”,任何看图的人都能找到自己在层级里的位置。
6.2 数据与样式分离:通过配置批量生成
当图的数量积累到一定程度,人工维护每一张图的样式会变成巨大的负担。这时候,我会把“数据”和“样式”分离:组件和连接关系用一种结构化的数据格式定义,样式规则单独配置,通过脚本批量生成最终图。
听起来有点工程化,但实践下来收益极高。有一次我需要在一份项目文档中绘制某图像处理Demo的模块结构,人工画大概要半天,而我把模块清单和依赖关系写成一个配置文件,写了一个小工具批量生成图,半小时就完成了。更重要的是,之后每次模块变化,改配置文件立刻就能生成新图,再也没有“图没更新”的问题。
6.3 在文档工作流中配置自动校验
结合前面的文本化工具实践,我在一些项目里给图的源文件配置了自动校验脚本。校验规则通常包含以下几类:源文件语法是否能正确解析、是否存在指向未定义组件的连线、是否存在孤立组件、是否包含未标注方向的连线。
这套自动校验已经帮我在好几个关键时刻救过场。最实用的一次是在评审前一天,我批量更新了多个模块图,跑了一遍校验,发现四个组件因为重命名没有同步更新导致连线断裂,我连夜修完,评审现场没有再出现“这张图是错的”这种尴尬。自动化的价值不是省略人工,而是在人工记忆失效的时候兜底。
我在实际使用中发现一个特别管用的小技巧:每次导出架构图时,同时导出文件名带版本号的SVG和PNG。这样在线文档用SVG保持清晰度,离线讨论用PNG快速加载,而且带上日期就能直接看到图的新旧,避免拿一张三个月前的图在会上讨论。画图这件事,越往后做越会发现,它的核心不是“画”的技术,而是“设计”的取舍:为谁画、画什么、不画什么,每一个决定都比鼠标拖出来的线条重要得多。