ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

代码驱动制图:用规范与工具链打造清晰一致的架构图与流程图

代码驱动制图:用规范与工具链打造清晰一致的架构图与流程图 diagram-design 这个名字听起来像是一个普通的画图项目但我在过去大半年里把它做成了一套完整的方法论加工具链。技术写作、方案汇报、系统设计每个场景都逃不掉一个痛点一张图能说清楚的事用文字绕三圈别人还是听不懂可真动手画图又常常陷入“图画出来了但丑到没人愿意细看”的窘境。diagram-design 就是冲着这个问题去的——它解决的问题不是“怎么把图画出来”而是“怎么把图表设计得清晰、一致、可维护”并且让整个过程可以交给代码和规范去约束而不是全靠个人感觉。这套东西适合谁如果你需要频繁产出架构图、流程图、时序图或者需要在团队文档里维护一批经常变动的图表那它基本能直接改善你的日常。无论你是写文档的工程师、做方案的设计师还是带项目需要画图讲清楚逻辑的人下面这些思路和步骤都可以照着复现。我会把项目背后的设计思路、工具选型、实操流程、踩坑记录都摊开讲尽量让你读完就能上手。1. 项目定位与核心设计思路1.1 为什么选择“代码驱动制图”这条路diagram-design 的核心选择是把图表用纯文本的方式去描述再用工具渲染成最终图形。这是跟传统“所见即所得”绘图最大的分岔口。Visio、draw.io、Figma 这类工具并不是不好它们胜在交互直观拖拽一下就能出图。但它们的短板也很明显图一旦多起来版本管理基本靠“另存为新文件”别人想改你的图得先安装同一个软件还得忍受图层被挪乱后的连锁反应。而代码驱动制图天然解决了这几个问题。我用一个类比来说明所见即所得工具像是在白纸上直接画油画落笔就定稿修改成本很高diagram-design 的做法则像用源代码写网页页面上看到什么不重要重要的是源码随时可以 diff、回滚、多人并行改最后用统一的方式构建出成品。这个选择并不是要否定 GUI 工具而是要在“快捷”和“可维护”之间找平衡。diagram-design 的思路是把图表的“内容结构”和“视觉样式”分开。内容结构用文本描述这部分进 Git 做版本管理视觉样式通过主题文件统一控制换风格不用动内容。实际用下来这套分离机制带来的收益远超预期尤其在团队协作的场景里几乎消灭了“那张最新版图在谁那里”这种问题。1.2 视觉一致性的三个设计原则很多图表丑不是绘制者审美不行而是没有一套可以重复执行的视觉规则。diagram-design 花了比较多精力在视觉一致性上提炼出三条原则。第一条是有限色板。一张图里颜色一旦超过五种读者就会开始怀疑“这个颜色是不是有特殊含义”。所以我把颜色收敛到一套固定语义核心组件用一种色、依赖的外部系统用一种色、数据流用一种色、告警或异常用一种色。每种颜色在主题文件里定义一次全项目复用谁画图都不许临时发明新色号。这样整套文档的图表放在一起看就像出自同一个人之手。第二条是统一的节点隐喻。节点用什么形状、圆角还是直角、边框虚实都要跟它的“语义”绑定。比如系统组件用圆角矩形外部依赖用直角矩形数据存储用圆柱决策点用菱形。这个规范听起来细碎但它是读者快速定位信息的抓手。人脑对形状的识别速度比对颜色更快形状有规律扫图的速度能快一大截。第三条是留白与网格。图表的疏密程度直接影响理解成本。diagram-design 里强制规定节点间距、连线拐点、分组padding这些参数对齐到统一的网格系统。这样做的好处是图上的元素永远有呼吸空间不会挤成一团。很多人画图觉得“信息太多放不下”其实不是真的放不下而是没有用网格去规划空间。网格不是限制它反而是让复杂图保持可读性的底层保障。2. 工具链选型与关键细节2.1 主流工具对比Mermaid、PlantUML、Graphviz、Excalidrawdiagram-design 在选工具的时候我把市面上常见的几类方案摆在一起对比过。这里直接给出我的对比维度语法表达能力、渲染效果、生态集成度、中文字体支持、版本管理友好度。工具语法表达能力渲染质量集成度中文字体适用范围Mermaid中上流程图/时序图/状态图都能覆盖现代简洁默认主题可用极好Markdown生态随处可用需要额外配置字体文档内嵌图首选PlantUML强时序图表达力突出偏朴素定制需要写样式一般插件支持为主支持较好偏 UML 的场景Graphviz极强布局算法多默认风格偏学术需调样式一般命令行工具依赖系统字体复杂拓扑、架构图底层渲染Excalidraw不依赖语法手绘风格手绘感强适合草图和头脑风暴中等提供文件格式好快速表达想法不追求严格规范Mermaid 是我最后的主选。它的语法简单到团队成员看十分钟就能上手而且 GitHub、GitLab 这些代码托管平台原生支持渲染文档里直接嵌代码块就能出图省掉了“图挂了”的问题。Graphviz 没有完全弃用遇到需要精确控制布局的复杂架构图我会先用 Graphviz 出布局再做后处理。PlantUML 只在画严格 UML 时序图时才会开毕竟它的时序图语法确实能打。需要提醒的是工具选型不要只看网上评测要看你的内容形态。如果你的图大量出现在 Markdown 文档里那 Mermaid 这类支持嵌入 Markdown 的工具就是最优解如果你主要画精美的对外汇报图那应该考虑 SVG 编辑类工具。diagram-design 的结论是默认 Mermaid遇到特殊场景再切换不追求一把锤子敲所有钉子。2.2 主题定制与样式统一的关键参数选好工具只是开始真正决定图表质感的是主题定制。Mermaid 默认主题其实挺好看但放到统一的文档体系里会显得跳。diagram-design 里做了一套团队主题核心做法是覆盖 themeVariables。以 Mermaid 为例我常在配置里干这几件事定义品牌主色作为 primaryColor定义边框色和阴影色调整字体为“等宽优先、中文回退”的字体栈设置全局圆角大小。这套变量配置一次整个项目的图都跟着走比手工逐张去调颜色高效太多。Graphviz 那边同理node 的 shape、style、fillcolor、fontname 全部写成默认属性放在一个公共配置里。主题统一的隐藏价值在后期维护时才会体现。项目跑了半年后会积累几十张图。如果每张图都是各自临时定义的颜色那改版的时候就是灾难。但因为有主题变量全局换肤只是改一行配置的事。这个“变量化”的思路其实是从前端开发里借鉴过来的套在图表上同样适用——把会变的东西收敛到少数入口剩下全是纯内容。3. 实操过程与核心环节实现3.1 搭建一个可复用的图表模板工程diagram-design 的实际操作不是打开在线编辑器画图而是先搭一个本地工程。这个工程里每个图都是独立的文本文件有统一的目录结构有渲染脚本有输出目录。这样整套体系是可复现的换一台机器也能直接跑起来。一个典型的目录结构是这样diagram-design/ ├── src/ │ ├── architecture/ │ │ └── system-overview.md │ ├── flow/ │ │ └── order-process.md │ └── sequence/ │ └── auth-sequence.md ├── theme/ │ └── default.json ├── scripts/ │ ├── render.sh │ └── check.sh └── dist/ ├── svg/ └── png/src 目录按图表的类型分子目录每个 md 文件里可以放一张图的 Mermaid 源码和必要说明。theme 目录放主题配置scripts 里放渲染和校验脚本dist 是产物目录。渲染脚本我用的是 Node 生态里的工具组合核心逻辑是读取每个 md 文件里的代码块调用 Mermaid 的 CLI 生成 SVG再用工具把 SVG 转成 PNG。脚本本身不复杂但它把“画图”这个动作变成了“编译”每次改完内容跑一下命令就能更新所有产物。这个体验跟写代码很接近也更容易被工程师接受。3.2 设计一张架构图的完整步骤拿画一张系统架构图举例diagram-design 的流程分四步。第一步是列组件清单。先把所有要出现的系统、模块、数据存储写出来不急着画连线的正确性永远优先于美观。第二步是定分组。架构图一般按层级或区域分组比如“应用层”“服务层”“数据层”Mermaid 里用 subgraph 来表达这样读者第一眼就能抓住大结构。第三步是连线。连线只表达真正的依赖关系宁可少画也不要画一堆“可能有关系”的虚线图上的线越少核心链路越突出。第四步才是调样式。用主题变量统一外观检查有没有节点溢出、线穿节点的问题。布局这块Mermaid 默认的流向是上下TB但架构图很多时候用左右LR更合适。我一般根据目标载体决定流向文档里嵌入式阅读的图用 TB 更自然投屏汇报用的架构图用 LR 更能利用宽屏空间。这个决定要在画图前就做好中途切换流向往往要调整整张图的逻辑顺序成本很高。3.3 在团队协作中落地自己用一套方案不难难的是让整个团队都按这个方案产出。diagram-design 在团队落地时我做了三件事。第一件事是沉淀一个“最小可用规范”文档只规定必须遵守的内容文件放哪里、命名格式是什么、颜色语义是什么、什么场景用流程图什么场景用时序图。规范不用长两页以内太多规则没人看约等于没有。第二件事是提供模板和示例新人入队不需要从头理解规范直接复制已有图的文件改内容就行比背规范快得多。第三件事是接入代码评审流程图表文件也是代码变更也走评审评审里重点看语义有没有偏差接缝处有没有断档颜色形状是否符合规范。这套机制跑起来之后效果很明显图表不再是一个人维护的稀缺资源而是团队共享的“文档资产”。谁要改架构图直接改对应文本文件提交一次变更全链路透明。曾经那种“图在某个同事的电脑里他请假了就没人能动”的情况彻底成为历史。4. 常见问题与排查技巧实录4.1 布局乱、节点重叠怎么办用 Mermaid 画图时最容易遇到的是节点重叠和连线乱飞。我第一次画一张有二十多个节点、还有跨组连线的架构图时渲染结果简直没法看文本框叠在一起线绕了大半个图。后来排查下来问题大多出在子图使用不规范和节点顺序上。一个很实用的排查套路是先删掉所有 subgraph 看布局是否正常再逐个加回分组每次加一个就渲染一次马上能定位是哪个分组引发的问题。另一个套路是利用不可见连线来辅助排序Mermaid 的布局对节点声明顺序很敏感把想放在同一水平线的节点按顺序声明布局会稳定很多。还有一种情况是节点内容字数差异过大标题长的节点会把整行撑得很宽这种情况下可以给文字换行让节点比例回到合理范围。Graphviz 的布局问题不太一样它提供了 rankdir、rank、constraint 这些精细控制手段。遇到自动布局不满意又不确定怎么调的时候我的经验是优先加 invisible edge 来微调节点相对位置而不是去改全局算法参数。全局参数一改往往是修好了这个图弄坏了另一个。4.2 中文字体与导出乱码的处理中文用户的头号坑一定是字体问题。Mermaid 默认字体对中文不友好导出的 SVG 在别人电脑上打开经常出现豆腐块或者缺字。这个问题我在项目初期就遇到了当时生成的 PNG 图里中文全部变成方框排查了好久发现是渲染环境里没有中文字体。解决分两步走。第一在配置里显式声明字体栈让 Mermaid 知道优先用系统的中文字体比如 “PingFang SC”、“Microsoft YaHei”、“Noto Sans CJK SC” 这一组英文和数字用等宽字体渲染。第二确保渲染环境真的装了这些字体尤其是使用 Docker 或者 CI 流水线时镜像里多半没有中文字体需要在构建阶段就安装好否则配置写再多也没用。还有一个小细节值得注意导出的 SVG 里文字是矢量渲染成 PNG 时如果字体缺失不会报错只会静默变成豆腐块。所以我在渲染脚本里加了一步自动检查统计生成图片里是否有异常字形提前发现这类问题而不是等图片用到了文档里才被肉眼发现。4.3 多人协作时的冲突处理当图表文件进入 Git 之后多分支并行开发很容易产生冲突。普通代码冲突大家都会处理但 Mermaid 这种文本也会冲突比如两个人在不同分支同时往一张架构图里加节点合并不当会把整个语法搞坏。我的处理习惯有三个。第一让连接关系成为主要的冲突识别依据合并时优先看连线是否指向已经删除的节点这是大部分合并后报错的根源。第二尽量细化拆分一张图别画到无敌大超过一定复杂度就拆成子图不同子图放到不同文件冲突概率能指数级下降。第三在文件头部用注释块写上维护提示比如“本图表由系统 A 团队维护改动前先联系负责人”这算是个软约束但在团队里很管用能减少大量无谓的竞争性修改。4.4 常见问题速查表我把平时在项目里被问得最多的问题整理成了一个速查表方便直接对照处理。现象可能原因处理办法文字变成方框渲染环境缺中文字体安装字体并配置 fontFamily节点重叠严重子图过多或声明顺序不合理逐个加 subgraph 定位问题调整节点顺序连线穿节点跨组连线过多重构成多个子图并适当使用不可见连线布局方向不对未指定流向或容器宽度过窄明确设置 TB/LR调整图宽Git 合并冲突多人修改同一文件拆分文件减少单图复杂度导出的 PNG 模糊放大倍数不够用 SVG 作为源格式按目标尺寸导出运行时语法报错特殊字符未转义检查引号、括号必要时用实体编码5. 从“能画图”到“画好图”的进阶心得5.1 图表的分层表达diagram-design 走到后期最关键的认知变化是好的图表从来不是把所有信息塞进一张大图而是把信息分层表达。一个复杂系统从上到下可以分为全景图、子系统图、模块细节图三个层级。全景图给投资者或新同学看只展示系统边界和核心链路子系统图给相关研发看展示模块之间的关系模块细节图给具体开发者看细化到类、接口、数据字段。很多人画图喜欢“一张图概括一切”最后的结果就是图里每个元素都很小谁也看不清谁也找不到自己关心的部分。我现在的习惯是在一张新图动笔前先问一句这张图的读者是谁他们需要从这里获取什么行动信息。回答清楚这两个问题图的内容裁剪就水到渠成了。分层的额外好处是每张图的维护成本都低改一个模块不用动全景图不会出现“改一行牵一发动全身”的局面。5.2 建立自己的素材库画图画多了会发现大量场景是重复的。比如各种系统架构图里都会出现网关、认证中心、消息队列、数据库这些组件如果每次都从头画效率低而且很难保持风格统一。diagram-design 专门建了一个素材复用库把这些高频组件和典型子结构的文字模板沉淀下来。这个素材库不复杂就是一组带参数的模板文件。画网关节点用哪种颜色和图标、画外部系统用什么边框全部有现成模板可复制。素材库的价值在于新图画起来快而且天然与既有图风格统一。另一个好处是改模板就能全局更新比如想把所有外部系统的边框改个颜色只需要改模板存量图里的样式甚至不用动重新渲染一遍就生效了。5.3 这套体系的后续扩展方向diagram-design 当前的状态已经能支撑日常图表工作了但我还有一些规划中的扩展方向。最优先的方向是接入实体关系和数据流校验让图表不仅仅是一张好看的图还能在渲染时自动检查出不一致的连线或空引用。另一个方向是沉淀一套针对不同场景的最佳实践示例集让团队同学在接到画图任务时能直接找到参考案例而不是每次都在讨论“这里的节点到底该用圆角还是直角”。这些扩展不需要改变现有工具链Vite 依赖、CI 脚本、文件组织都能平滑演进。diagram-design 对我来说最大的启示是画图这件事看起来是感性工作但把它当作一份带规范的代码去工程化管理之后效率和质量的提升是非常明显的。很多时候我们觉得某个工作做不好不是能力问题而是没找到合适的方法来约束它。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进