做技术方案的同学,大概都经历过这样一个场景:评审会上对着架构图讲得眉飞色舞,底下的人频频点头,散会两周以后,画图的人自己打开那张图,盯了半天也没想起来每个框和箭头到底想表达什么。直到我认真把diagram-design当成一门正经技能来练,才意识到问题不在工具,而在思路。diagram-design,直译是图表设计,但它远不只是“拿工具画个框、拉条线”那么简单。它是把系统结构、业务流程、消息顺序、依赖关系这些抽象信息,转成一种别人能在几分钟内看懂的可视化表达。这件事做得好,一张图顶三千字;做得不好,图上每个框都是在帮倒忙。这篇文章把我从需求拆解、图型选型、布局设计、工具选型,到最终画完一张部署架构图的完整过程写出来,所有坑都是亲自踩过的,适合开发、架构师、产品经理和长期被技术文档折磨的同行参考。
1. 内容整体设计与思路拆解
1.1 图表设计的本质不是画图
很多人把diagram-design理解成“把东西画好看”,这个方向一开始就偏了。图表设计的本质是信息传达:你想让读者从图里获得什么结论,比图本身长得怎么样重要一百倍。
我做过的某订单处理系统架构图,前后改过五版。第一版把所有服务、数据库、缓存、消息队列、监控组件全部铺在一张图上,密密麻麻像电路板。评审时大家沉默了三分钟,然后一位同事问:“这张图到底想让我看什么?”我答不上来。后来我把图拆成三张:一张部署架构图,解决“服务跑在哪、流量怎么走”;一张业务时序图,解决“一笔订单从下单到支付完成经过哪些环节”;一张数据模型图,解决“核心表之间的关系是什么”。拆完之后,每张图都有了明确的阅读目标,信息传达效率立刻上来了。
这个案例说明一件事:diagram-design的第一步不是打开工具,而是先回答“这张图要给谁看,看完之后他希望做什么决定”。给运维看,你要突出端口、实例数、故障域;给产品看,你要突出功能模块和业务边界;给新入职的同学看,你要突出主流程和依赖关系。受众不同,同一套系统可以画出完全不同的图。
1.2 为什么说“图也需要设计”
人们总觉得写代码需要设计模式,写文档需要提纲,唯独画图好像很随便,打开画板就能画。实际上图表设计同样需要设计过程,而且它需要的信息架构能力一点都不比写代码低。
我归纳了图表设计的四个关键环节:
- 信息筛选:决定哪些信息要出现在图上,哪些信息要丢掉。大部分失败的图,问题都出在“什么都不舍得丢”。
- 结构组织:决定信息之间的层级关系。谁是大模块,谁是小组件,谁和谁属于同一层。没有层级的图,就相当于没有缩进的代码。
- 视觉编码:决定用形状、颜色、线型、箭头来区分不同类型的信息。形状往往代表组件类型,颜色往往代表状态或环境,箭头代表数据流或调用关系。
- 可读性优化:决定字体、间距、对齐、比例。这些看起来是“美化”,实际上是在降低读者的认知负担。
这四个环节缺一不可。只做第一步和第二步,图画出来往往“对但难看”,读者没有耐心看下去;只做第三步和第四步,图好看但没有内容,典型的“花架子”。
1.3 一条可复用的设计链路,而不是一上来就画
我踩过一次很深刻的坑。某次画一个跨平台系统的集成方案图,我打开工具就开始拖框框,边拖边想,结果两张图画下来发现结构推翻了三次,浪费了一个下午。后来我强迫自己按照下面这条链路走,效率高了很多:
明确读者和决策需求 -> 确定图表类型 -> 梳理核心信息清单 -> 设计布局骨架 -> 逐层补充细节 -> 评审迭代
你可能会觉得这步骤多此一举,但绝大多数难看的、没人能看懂的图,恰恰是因为跳过了中间某一步。尤其是“确定图表类型”这一步,很多人直接在架构图里硬塞流程图的内容,或者在时序图里同时描述部署关系,最后画出来一个四不像。
2. 图表类型选择与适用场景
2.1 不同图型的适用边界
图表的类型不是随便选的,每种图都有它擅长的表达维度。我自己常用的图型有这么几种,各有各的适用场景,我用一个表格整理了一下:
| 图型 | 表达重点 | 典型场景 | 不适合表达的东西 |
|---|---|---|---|
| 架构图 | 系统的组成部分和它们之间的关系 | 部署架构、模块依赖、微服务拓扑 | 时间顺序、流程分支 |
| 流程图 | 事情按什么顺序执行 | 业务流程、审批流程、异常处理 | 系统组件间的物理位置 |
| 时序图 | 对象之间消息交互的时间顺序 | API调用链、事件驱动流程、分布式事务 | 静态的组件归属关系 |
| ER图 | 数据实体及关系 | 数据库设计、数据模型评审 | 运行时调用关系 |
| 状态图 | 一个对象的状态迁移 | 订单状态、任务生命周期 | 多对象间的交互 |
| 部署图 | 物理节点和软件部署关系 | 机房/云环境部署、网络拓扑 | 代码级的类依赖 |
选图型的核心判断标准是:你想让读者沿着什么维度去理解信息。想沿着“时间”理解,就选时序图或流程图;想沿着“空间结构”理解,就选架构图和部署图;想沿着“对象状态”理解,就选状态图。
2.2 架构图最容易犯的错:承载了太多内容
架构图是diagram-design里使用频率最高、也最容易翻车的图型。大家总觉得一张系统架构图就应该把所有东西都画进去,Service、Database、MQ、Redis、网关、监控、配置中心、日志系统,全都塞在一起,结果就是一张图里塞了五个层面、三十个节点、二十条线,读者完全不知道该先看哪里。
架构图正确的做法是分层表达。我画某跨平台系统的架构图时,就把图分成了用户层、接入层、服务层、数据层、基础设施层五个横向条带。每一条带里放该层的关键组件,层与层之间用明确的箭头表达调用或数据流。读者从上往下读一遍,整个系统的运转逻辑就出来了。分层不是唯一的组织方式,但它是架构图里最稳定、最不容易出错的骨架。
2.3 时序图在设计里的特殊地位
时序图在技术文档里往往被低估。很多同学习惯用一大段文字描述一次接口调用过程,写的人费劲,读的人更费劲。但用时序图几根线就能把“谁调用谁、传什么参数、返回什么结果、超时了怎么办”表达得清清楚楚。
画时序图的关键是确定生命线和激活条。我一般先把参与交互的对象列在顶部,比如客户端、网关、订单服务、库存服务、支付服务,然后按时间顺序逐条画消息。这里有个容易被忽略的细节:消息上一定要标注协议名称或者方法名,比如HTTP POST /api/order/create,否则图看起来像那么回事,实际上没有任何信息量。
2.4 ER图与状态图的取舍
很多系统设计里,数据模型和状态迁移反而比接口调用更复杂。比如一个订单系统的状态:待支付、已支付、已发货、已完成、已取消、售后退款中,如果不画状态图,新同学根本理不清状态之间的合法流转。我后来有一个习惯:凡是状态超过六个的领域对象,就强制画一张状态图,用箭头标出每一次状态转移的触发条件。这种图对后续开发时的合法性校验特别有价值。
3. 图表设计的核心实操原则
3.1 信息分层是最高优先级的设计动作
我评审过很多同事的图,发现一个规律:凡是让人一眼看不明白的图,几乎都是在信息分层上出了问题。所谓分层,就是在视觉上把信息分成“一级信息”和“二级信息”。一级信息是所有读者都应该第一眼看到的,通常包括主流程起点、主链路、核心节点、数据落库;二级信息是所有辅助理解的,比如超时重试、备用链路、非关键依赖。
在实操上我有两个做法:一是用大面积色块或者虚线框把层次分出来,比如把“核心链路”整体框在一条浅色带里;二是把不重要的信息降级,比如把次要服务的连线改成灰色虚线,让注意力自动聚焦到主链路上。千万不要全图都画同等粗细的黑线,那是把所有信息放在同一个优先级上,等于没有优先级。
3.2 布局与对齐:决定的不是美观而是理解速度
布局里面最容易被忽略的一条是“流向一致性”。一张图里,数据流如果一会儿从左往右、一会儿从右往左、一会儿又自下而上,读者读图的视线就会来回跳跃。我自己的约定是:流程图和数据流图一律从上往下或者从左往右,而且同一张图里只能选一个方向。跨过这个约定之后,我画出来的图被评为“突然好懂多了”,其实我只是把线捋直了。
对齐同样能直接影响信息接收。图上的节点尽量保持相同的外边距,垂直方向尽量对齐到网格。很多拖拽式工具都有吸附网格功能,但大多数人画到一半就把吸附关了,因为拖动更“自由”。我建议你画完之前不要关吸附,自由拖拽出来的图,连线一定是歪歪扭扭的,节点间距一定忽大忽小,这种图看久了会让人觉得很不专业。
3.3 配色方案:颜色要承载语义,不是用来装饰
我给图配色的原则非常死板:颜色数量不超过五个,且每种颜色都有明确的语义。比如统一用绿色标识健康的、运行中的节点,用橙色标识需人工关注的部分,用红色标识失败或者异常路径,用灰色标识辅助或外部依赖。这样设置的好处是,读者只要瞄一眼图例,再看任何一个节点的颜色,就能立刻判断它处于什么状态,不需要逐字阅读。
这里有一个经验之谈:不要大面积使用高饱和度的颜色。大面积正红色做底色的节点框,看起来非常刺眼,容易引发视觉疲劳。我比较常用的是“低饱和底色 + 深色文字”的组合,简单说就是底色不要太浓,让文字保持优先可读性。另外,如果你画的图要打印成黑白文档或者被色弱的同事阅读,那你还得保证“去掉颜色之后,图依然能看懂”。这个要求很高,但绝对值得养成习惯。
3.4 命名与标注:信息在细节里
技术图里最影响理解质量的一个细节,就是节点命名到底是用“中文昵称”还是“真实服务名”。我见过太多图,代码里明明叫order-service,图上却写着“订单中心”,配置中心里叫order-svc,文档里叫“订单服务”。一个人三个名字,团队沟通的时候不得不在脑子里做一层映射。我的建议是图上标注以代码和服务注册名为准,中文注释作为括号备注。例如order-service(订单服务)。这样看图的开发能直接找到代码对应位置,看文档的产品也知道这代表订单模块。
线上的文字不要写太多。箭头上的文字,要么是流量方向描述,要么是接口名,要么是数据传递的关键字段。一句话能让读者知道“为什么这里要有一条线”就够了。整张图塞满解释性长句,那不是图,是带框框的作文。
3.5 可读性的底线约束
最后一条实操原则是做可读性自测。我画完一张图之后,会做两件很机械的事:第一,把图缩小到60%看整体结构,如果缩小的图中无法辨认主链路,说明图的信息密度已经超出合理范围;第二,把图放大到200%,看任意两个相邻节点之间是否能快速定位到对应连线,如果连线交叉过多,说明布局需要重做。
另外提一下字体和字号。图上中文至少用微软雅黑或者思源黑体,西文使用等宽字体可以增强对齐感。正文字号不要少于12px,注释字号可以用10px但千万别用8px糊弄,打印出来的效果会让你后悔。
4. 工具选型解析
4.1 主流的图表工具横评
工具选型在diagram-design里很关键,因为工具决定了你画图的体验效率和协作边界。我用过的几款主流工具,各有各的脾性,简单做个对比:
| 工具 | 类型 | 实时协作 | 版本管理 | 上手难度 | 适合场景 |
|---|---|---|---|---|---|
| draw.io | 网页/桌面拖拽式 | 配合存储可协作 | 配合Git管理文件 | 低 | 通用架构图、流程图、ER图 |
| Excalidraw | 网页手绘风格 | 强 | 一般 | 低 | 快速草图、头脑风暴 |
| Figma | 网页设计工具 | 强 | 很好 | 中 | 高保真界面图、复杂视觉设计 |
| PlantUML | 文本化 | 一般 | 非常好 | 中 | 时序图、类图、部署图 |
| Mermaid | 文本化 | 一般 | 非常好 | 低 | 文档内嵌图表、Markdown/README配图 |
| ProcessOn | 网页拖拽式 | 强 | 内置版本 | 低 | 在线协作、思维导图、架构图 |
| Visio | 桌面拖拽式 | 一般 | 一般 | 中 | 传统企业网络拓扑、机柜图 |
4.2 文本化工具为什么值得认真对待
我在很长一段时间里都是纯拖拽派,直到有一次,我在某跨平台系统文档里嵌入了用Mermaid画的时序图,发现整个协作体验发生了质变:图的源文件是一段文本,可以直接参加代码评审,可以diff,可以追溯到具体提交,还可以跟代码放在同一个仓库。这些能力是传统二进制绘图文件给不了的。
拖拽式工具画出来的图存在哪?要么存在云盘,要么存在本地,跟代码之间很难建立联系。而文本化工具画出来的图,跟Markdown文档一样进入同一个Git仓库,改图就是改代码,review就是把diff拿出来一行一行的看。这个优势在团队协作里太大了。所以如果你的图量不大,我建议优先考虑Mermaid和PlantUML;如果大量画架构图,draw.io配合Git存储也是很好的组合。
4.3 选型判断标准
我给选型总结了几条可执行的判断标准,碰到具体项目可以直接对着打分:
- 团队里谁会看图:如果全部是技术人员,优先文本化;如果产品、运营也会看图,拖拽式可能更友好。
- 图要不要跟着代码走:要走,优先文本化;只是一个独立交付物,拖拽式的效率更高。
- 协作频率:多人实时改,选在线实时协作强的工具;单人长期维护,选文件管理清晰、能进Git的工具。
- 图形复杂度:消息交互多,文本化工具的时序图体验好;物理拓扑多,拖拽式的图标库更省力。
工具是手段,不是目的。不要因为某款工具有漂亮的高级功能就选它,要看它能不能塞进你现有的团队协作流程里。
5. 实操过程与核心环节实现
5.1 实操目标:画一张部署架构图
下面用一张真实工作里最常见的图来走完整流程。场景是这样的:某订单处理系统上线前,需要一张部署架构图,给运维、开发、测试三个角色评审用。目标很明确,就是要解答三个问题:请求进来之后怎么走?系统依赖了哪些中间件?如果故障发生了,最可能在哪一层体现出来?
我事先整理的核心信息清单包括:负载均衡接入层、业务服务实例、缓存集群、消息队列、主从数据库、监控告警组件、日志收集链路、配置中心。这些信息是画这张图绕不开的骨架,也是评审中最常被追问的节点。
5.2 第一步:确定受众和呈现维度
我拿着需求去找运维确认了几个细节:他们最关心的是对外IP、端口、实例数、健康检查路径;开发最关心的是服务间的调用关系和依赖中间件的连接方式;测试关心的是环境隔离和日志链路。三类人关心点重叠的部分就是这张图的一级信息,各不相同的就是二级信息。
这样一来,我画的这张部署架构图在维度上明确为“物理部署 + 服务依赖”二合一,不涉及具体业务功能,那些功能细节留给另一张业务架构图。这是diagram-design里很关键的自觉:不试图在一张图里满足所有人的所有诉求。
5.3 第二步:搭建布局骨架
布局我采用标准的分层模型,从上到下一共四层:
- 接入层:Nginx 集群,负责 TLS 终止、路由分发和健康检查。
- 服务层:订单服务若干实例,水平扩展,注册中心做服务发现。
- 中间件层:Redis 缓存集群、消息队列、配置中心。
- 数据层:关系型数据库一主两从,和一个对象存储,用于存放流程日志附件。
第一版骨架先不要连线,只把每一层用横向泳道框起来,每个核心组件先用矩形占位。泳道的好处是:就算连线还没画,读者也能从物理位置直观感受到系统分了几层。这一步往往只花五分钟,但为后面所有操作提供了稳定的画布。
接下来给每个节点一个明确的名字。我统一采用“服务注册名 + 中文描述”的格式,比如 order-service(订单服务),Redis-Cluster(缓存集群),消息队列则标注为MQ。每个节点上我还预留了端口或者实例数的位置,后面细化时直接填。
5.4 第三步:逐步连线与数据流标注
连线是整张图的灵魂。我从左上角接入层开始,一笔一笔地标注流量路径:用户请求进Nginx,Nginx把请求转发给order-service其中一个实例;order-service先查Redis缓存,缓存未命中去查主库;写操作和异步任务通过MQ发送事件;配置中心给所有服务下发配置;日志收集组件从所有服务节点采集日志,写入日志存储。
连线时定了一个规则:实线代表同步调用或请求,虚线代表异步消息或事件通知,箭头方向统一朝数据流动方向。为了不让线交叉,我调整了中间层的位置,把MQ放在服务层和数据层之间偏右的位置。调整线交叉这件事,本质上就是在优化读者的视线路径,宁可多拉几次线,也不要给读者留下一个迷宫。
5.5 第四步:补充关键细节与图例
光有主链路还不够,评审时肯定会有人问“Redis挂了怎么办”“数据库主从延迟怎么处理”。我把这些容灾路径用不同颜色标了出来:Redis不可用时直接穿透到主库,用橙色虚线标识;消息队列长时间积压触发告警,在MQ节点旁加了一个小的告警图标,同时在图下方补充说明,避免图面过于拥挤。
图例放在左下角,所有用到的颜色、线型、图标含义列出两三行。这是最容易被人省略、但价值最高的一步。没有图例的彩图,读者只能靠猜。
最后我还加上了版本号和日期,在右下角标了V1.2和修改时间。别小看这一行,没有版本号的图,在共享协作里就是一颗定时炸弹,回头有人拿着旧图来跟你对质,你连自己画的是哪版都说不清。
5.6 第五步:找人评审,而不是自己欣赏
图画完以后,我找了三个人做了三分钟交叉评审。运维问了一句“Nginx的直接返回的页面是否依赖动态配置”,我意识到图上没有体现Nginx侧的配置中心依赖,于是补了一条虚线。开发问“消息队列的主题和消费者组是不是只画到了组件级别,没有画到主题级别”,这个确实太细,我选择了在备注里补充,而不是往图上加更多框。
评审的意义就在于,你一个人画图时的盲区,在别人眼里一目了然。这个环节不能省,而且建议至少找两个不同角色的人来看,因为不同角色看到的问题完全不一样。
6. 常见问题与排查技巧实录
6.1 高频问题速查表
做diagram-design这么长时间,我碰到的高频问题基本集中在下面这些,整理成速查表给各位参考:
| 问题 | 现象 | 排查思路 |
|---|---|---|
| 图太大,信息过载 | 读者盯着图不知道该看哪里 | 拆图,一张图只讲一个核心维度;把二级信息降级或移除 |
| 配色杂乱 | 红黄蓝绿紫全部出现 | 限制到5种以内,且每种颜色赋予明确语义 |
| 箭头方向混乱 | 数据流一会左一会右 | 全图统一一个主流向,推荐从上到下或从左到右 |
| 命名不一致 | 图上名称与代码/配置不一致 | 统一以代码服务名为准,中文仅做备注 |
| 没有图例 | 读者看不懂颜色和线型 | 完整图例直接放进图内,不要只在汇报时口述 |
| 版本随意覆盖 | 图改完旧版丢失 | 用Git管理文件,或至少保留带日期的版本副本 |
| 线型无区分 | 同步、异步、备用链路全靠一种线 | 约定实线/虚线/点线对应不同关系并写进图例 |
6.2 踩过的三个大坑,每个都花过冤枉时间
第一个坑是过度设计。有一段时间我沉迷把图标画得很精致,每个节点加了渐变色、阴影、圆角,连Nginx的logo都要去找高清版。结果图好看是好看,但因为文件太大,协作平台上加载都要转圈,而且每次小改动都要重新对齐一堆图形样式。后来我果断放弃了所有装饰性设计,只保留矩形、圆角矩形、菱形和箭头,整张图的绘制速度提升了三倍,可读性反而更好了。
第二个坑是信息过载。有一次画一个某跨平台系统的架构图,我把所有的服务、配置、限流规则、消息主题全画进去了,结果评审会上大家完全看不过来找重点的能力,评审时间有一半花在“先带大家看图”上。从那以后我给自己立了规矩:一张图聚焦一个核心维度,超出的部分要么拆图,要么把次要信息移到附录文本里。这是diagram-design里“少即是多”最具体的落地方式。
第三个坑是方向不统一。早年的时序图里,我经常随意调整对象的位置,导致消息走向有时候从左往右,有时候从右往左。画的时候觉得无所谓,读图的时候才发现视线来回跳很难受。后来我画时序图强制自己按“发起方在最左,目标服务向右排列”的顺序摆对象,消息流自然就稳定了。方向统一,是看起来微不足道但对体验影响最大的改动。
6.3 让团队真正接受图表的几个实用技巧
经常有人说“我画了图,但大家还是不看文档,都来私聊问”。我觉得问题往往出在图的入口和图的时效性上。
入口问题:图要放在大家找得到的地方。如果图存在某个人的网盘私人目录里,不如直接放进代码仓库的docs目录,并在README里引用。我在团队里就把主要的架构图和时序图都改成了文本化工具格式,写进Markdown文档,任何人打开仓库就能看到,还能顺手提PR修正。图一旦能跟着代码走,被阅读的概率就大大提升。
时效性问题:图最怕的是过时。我在每个图里都醒目标注了版本号和更新时间,并且把“改代码必须同步改图”写进了团队的开发规范。每次代码评审时,会检查涉及模块的图是否同步更新。这个习惯坚持下来之后,图才真正变成了团队的高可信资产,而不是一堆历史遗迹。
6.4 日常维护成为硬功夫
最后一点心得:diagram-design不是一次性行为,它是持续维护的工程资产。图跟代码一样,需要review,需要版本管理,需要偶尔重构。我个人的习惯是每隔一个迭代周期,打开核心图看一下,看看有没有新组件没画上去、有没有旧组件需要下线、有没有箭头方向需要调整。
这个维护动作听起来很繁琐,但它带来的回报非常直接:当团队遇到问题时,有一张可信的图可以让大家讨论,不用再靠高年级同学口述记忆。往大了说,这其实就是团队知识沉淀的一种形式,而diagram-design就是那个沉淀的工具。
我个人的体会是,画图这件事,真正拉开差距的从来不是谁的工具更高级,而是谁对信息结构的理解更清楚。每次画完一张图,我都会问自己一个很土的问题:如果三周后的我打开这张图,能不能不靠任何解释就完全看懂?如果答案是不能,那就说明这张图还有设计上的偷懒。这个标准不高,但能拦住大部分看起来很美的废图,值得你试试。