活文档架构:让你的文档始终保持最新
上周二有人合并了一个新增服务的 Pull Request,然后就什么都没发生。没有图表发生变化,没有 ADR 被写下,而那次审查是认真细致的。没有人提到架构,因为被审查的本来就不是架构。
这就是本文的主题。不是文档会变陈旧这件事本身——那件事由架构漂移指南连同如何检测一起讲——而是它本可以保持最新的那唯一一个时刻,在一个正常的、运转良好的工作流内部悄悄溜走了。活文档就是让那个时刻不被漏掉的那一整套安排。这是问题的实践那一半:五种策略、每一种的代价,以及每一种会在哪里失效。
什么让文档成为"活的"?
活文档有三个区别于传统静态文档的核心特征。
自动更新
活文档不完全依赖人类记住去更新它。文档的至少某些方面是从系统本身衍生出来的——来自代码、来自部署、来自基础设施、来自 API 定义。当系统变化时,文档反映这些变化,无需人工干预。
这并不意味着一切都是自动化的。架构意图、设计理由和战略决策仍然需要人类来撰写。但文档中事实性的、结构性的部分——存在哪些服务、使用什么技术、它们如何连接——可以而且应该被自动化。
持续验证
活文档包含检测其何时与现实偏离的机制。不是等到有人读到陈旧文档并意识到它是错误的,验证机制会主动捕捉漂移。
在实践中这是两种不同的检查,下面的策略 3 会把它们清楚地分开:合规性规则,检验模型是否符合你设定的标准;以及漂移检测,检验模型是否仍然符合代码库。两者都可以在 CI 中运行。两者一旦朝错误方向移动,都值得发一条告警。
融入开发工作流
活文档不是在单独的流程中维护的。它集成到开发工作流中——与编写、审查和部署代码的工作流相同。架构变更通过 Pull Request 进行。文档更新与代码变更同时发生。文档存在于开发者已经工作的地方。
静态文档的问题
改变工作方式的理由在于:另一条路有固定的形状,而当你见过它两次之后,就能提早认出来。
创建-衰变循环
靠良好意愿维护的文档遵循一个可预测的循环:
- 创建:一个有积极性的团队成员(或架构师、或顾问)写下了文档。它是准确的、详细的、组织良好的。
- 有用期:在几周或几个月内,文档是有价值的。团队成员引用它。新员工从中学习。
- 首次漂移:一个变更发生了——一个新服务、一个重命名的组件、一个改变的依赖。文档没有被更新,因为做出变更的开发者没有想到、不知道文档在哪里、或者没有时间。
- 加速衰变:一旦第一个不准确出现,衰变速度就加快了。每个后续变更被反映在文档中的概率都更低。信任按比例下降。
- 弃用:最终,文档过时到没有人信任它。它变成了"系统过去是什么样子"的参考材料,而不是它实际的样子。
- 重新创建:有人意识到问题并从头创建新文档。循环重新开始。
代价最高的是第 6 步。每一轮创建都要花费实打实的精力,而其中大部分被用来重新推导上一轮已经知道的东西,因为在两次尝试之间,整套安排一点没变。如果你的团队正在第二次或第三次重写同一份架构文档,那问题从来就不是写作本身。
人力瓶颈
静态文档完全依赖人类做额外的事情。完成一个功能后,开发者需要记得更新架构图。设计会议后,有人需要将白板讨论转化为结构化文档。重构后,有人需要验证所有受影响的图表是否仍然准确。
这些都是手动步骤,与其他优先事项竞争。在大多数组织中,更新文档的优先级低于编写代码、修复 Bug 或赶截止日期。结果是可预测的:文档落后了。
发现难题
即使文档是准确的,也常常难以找到。架构图在 Confluence 中。API 规范在另一个工具中。ADR 在 Git 仓库中。技术选型记录在 Wiki 中。没有一个单一的地方能给你完整的全貌,开发者浪费时间在工具之间搜索——如果他们去搜索的话。
活文档架构的策略
让文档真正活起来需要组合多种策略。没有任何单一方法足够,但组合在一起它们创建了一个以最小手动工作保持文档时效性的体系。
策略 1:代码驱动的文档
保持文档时效性最有效的方式是从代码中派生它。如果文档是从系统的源代码、配置或基础设施定义生成的,它就不会漂移——因为它总是从当前状态重建的。
Architecture as Code 是这一策略最直接的实现。不是在可视化工具中画图并寄希望于有人去更新它们,而是在 Git 仓库中的 YAML 文件里定义你的架构。文件就是事实来源,可视化图表从中生成。
当开发者添加新服务时,他们在同一个 Pull Request 中向架构文件添加几行。变更与实现一起经过代码审查。CI/CD 流水线将更新后的文件同步到你的文档平台。图表始终是最新的,因为它总是从代码重新生成的。
API 契约生成是代码驱动文档的另一种形式。OpenAPI 生成器等工具可以从标注了注解的代码中生成 API 规范。不需要单独维护 API 文档,文档直接从实现中提取。代码变了,文档就变了。
在 Archyl 中,archyl.yaml 文件作为代码驱动的事实来源。你还可以通过 REST API 或 MCP Server 从构建流水线中以编程方式更新架构元素,确保自动化流程保持文档同步。
策略 2:AI 驱动的发现
即使有了代码驱动的文档,架构中仍有一些方面在代码中并不显式。一个服务可能使用了通过环境变量配置的数据库。两个服务可能通过基础设施代码中定义的共享 Kafka topic 通信。一个新服务可能存在于部署流水线中但还不在架构文件中。
AI 驱动的发现通过分析你的代码库、基础设施和部署产物来建议架构文档的更新,填补这些空白。
Archyl 的 AI 发现功能扫描你的代码仓库并识别:
- 尚未记录的新服务
- 存在于代码中但未反映在架构模型中的依赖关系
- 自上次文档更新以来已变更的技术栈
- 与已记录内容不同的通信模式
AI 不会自动修改你的文档——它建议由人类审查和批准的变更。模型说什么,每一处仍然由你拍板;你不用再做的,是四处寻找到底哪里变了。
策略 3:合规性规则和漂移检测
活文档需要两道护栏,而这两道护栏经常被彼此混淆,因为它们都会给出一个数字,也都会大声失败。它们衡量的是不同的东西。
合规性规则问的是:你的模型是否遵循你设定的标准。每个容器都写明了技术、每个外部系统都有描述、没有孤立元素。一个规则引擎评估它们并报告违规。
漂移检测问的是:你的模型是否仍然与代码库一致。它把文档化的架构与仓库做比对,返回一个 0 到 100 的评分。它对你的规则一无所知。
一个模型可以满足你写下的每一条规则,同时描述着一个上个季度就被重构掉、早已不复存在的系统。反过来也会发生:一个准确的模型,却违反了你一半的标准。两种检查你都需要,而且不该把其中一个数字当成另一个来读。漂移评分是如何计算的详细讲了后者,包括它看不到什么。
合规性规则示例:
- 每个容器必须至少记录一项技术
- 每个外部系统必须有描述
- 每个有数据库依赖的服务必须有已记录的数据所有权描述
- 不允许孤立容器(每个容器必须至少参与一个关系)
- 每个 ADR 必须引用至少一个架构元素
- 所有 API 类型的容器必须有关联的 API 契约
Archyl 内置了一个包含 169 条此类规则的目录,覆盖 23 项具名技术外加一套与语言无关的规则,所以大多数团队是从打开适用的那些开始,而不是自己动手写。违规是按元素报告的,这一点很重要:"七个容器没有记录技术"是一项任务,而"你的文档不完整"只是一种情绪。
漂移评分是单独计算的,可以按需触发,也可以从 CI 任务里跑;当它下跌十分或更多时,webhook 会被触发。两者合在一起,闭上了 Pull Request 留下的那个缺口:规则抓住从未完成的文档,评分抓住不再为真的文档。
策略 4:文档作为完成定义的一部分
活文档最有效的组织策略是将文档更新纳入任何影响架构的工作的完成定义。
这意味着:
- 如果一个 Pull Request 添加了新服务,架构文件必须在同一个 PR 中更新
- 如果一次设计会议产生了决策,在决策实施之前必须创建 ADR
- 如果 API 契约发生变更,已记录的契约必须被更新
- 如果一个服务被停用,它必须从架构模型中移除
这不是关于官僚主义——而是将"变更发生的时间"和"文档更新的时间"之间的差距缩减为零。当文档与代码变更在同一个工作流中时,它就不需要单独的工作。
Archyl 通过其 Architecture-as-Code 集成来支持这一点。当架构文件与代码存在于同一个仓库中时,在同一个 Pull Request 中更新两者就是自然而然的。代码审查者可以验证架构变更与实现一起被记录。
策略 5:持续可视化
活文档必须易于访问且在视觉上有信息量。如果开发者需要解析 YAML 文件才能理解架构,采用率就会受影响。基于代码的定义应该产生始终是最新的、始终可访问的、始终有用的可视化输出。
这意味着:
- 从事实来源自动重新生成的架构图
- 支持从 System Context 缩放到容器再到组件的交互式导航
- 突出特定方面(所有权、技术栈、通信模式)的叠加层
- 跨所有架构元素、关系和文档的搜索
Archyl 的可视化层是从模型读取的,所以无论那个模型是通过 YAML 文件、MCP Server、REST API 还是可视化编辑器更新的,图表都会呈现它当前的状态,不需要任何人重画。请准确理解这换来了什么:图永远与模型一致。至于模型是否与代码一致,那是漂移评分的问题,不是渲染器的问题。
衡量文档新鲜度
活文档应该是可衡量的。以下是重要的指标。
漂移评分
唯一能告诉你这套实践是否奏效的数字。它衡量你文档化的架构中还有多少仍然存在于代码库里;如果本文中的那些安排真的立住了,它就会停止下滑。在每次推送到 main 时从 CI 触发它,那条趋势线就是关于你工作流的诚实报告,而不是关于你意图的报告。
完整的机制、公式,以及它看不到的四件事,在单独的一篇文章里。
文档编写时间
衡量架构变更出现在文档中需要多长时间。在运作良好的活文档体系中,这应该接近零——因为文档更新发生在与代码变更相同的 Pull Request 中。如果存在持续的延迟,你的工作流集成需要改进。
覆盖率
跟踪你的架构有多大比例被记录了。多少服务有描述?多少关系有标签?多少容器有已记录的技术栈?覆盖率指标告诉你哪里存在空白。
信任调查
定期问开发者:"你信任架构文档吗?"如果答案是否定的,那么无论量化指标怎么说,你的活文档实践都需要改进。开发者的信任是文档质量的终极衡量标准。
常见陷阱
试图自动化一切
不是所有东西都可以或应该被自动化。架构意图、设计理由、权衡分析和战略方向需要人类来撰写。活文档自动化的是事实性的、结构性的方面,同时为人类洞察保留空间。
将合规性当作合规审查
合规性规则应该是有帮助的,而不是惩罚性的。它们的存在是为了捕捉无意的漂移,而不是制造官僚开销。如果团队花在满足合规性规则上的时间超过了做有用工作的时间,那规则就太严格了。
忽视新人入职场景
活文档应该对从未见过系统的人也是可访问的。如果你的文档需要深厚的上下文才能理解,那它就没有服务好它最重要的目的之一。定期通过从新人视角浏览文档来测试它。
让完美成为良好的敌人
你不需要完整的覆盖率和完美的漂移评分才能拥有有用的活文档。一张覆盖了大部分服务、每周更新的 Container 图,比一套六个月前还准确的完整文档更有价值。把 CI 阈值设在你今天所处位置的下方,等团队准备好了再往上调,而不是拿一个从没人达到过的数字来卡门。
Archyl 如何实现活文档架构
Archyl 从一开始就是为支持活文档实践而构建的。以下是每项能力的贡献。
Architecture as Code 使文档代码驱动。archyl.yaml 文件存放在 Git 中,经过代码审查,通过 CI/CD 自动同步。架构文件的变更立即产生可视化图表的更新。
AI 发现 通过分析你的代码库并建议更新来识别文档差距。它捕捉新服务、变更的依赖关系和更新的技术栈,否则这些可能不会被记录。
合规性规则 定义正确的文档应该是什么样子,并按元素报告违规。漂移检测 是另一项独立的检查:它把模型与仓库做比对,并为这个差距打分。规则抓住从未完成的文档;评分抓住不再为真的文档。
MCP Server 将架构文档集成到 AI 辅助开发工作流中。开发者可以从 IDE 中查询和更新文档,无需切换到单独的工具。
所有权映射 通过将每个架构元素映射到负责团队来建立责任制。当文档漂移时,负责团队被识别出来,可以采取行动。
协作功能——评论、变更请求和实时协同编辑——使文档成为团队活动而非一个人的负担。
发布跟踪和 DORA 指标 将架构文档与交付效能联系起来,提供关于架构决策是改善还是阻碍团队发布软件能力的持续信号。
开始使用
如果你的架构文档目前是静态的,以下是让它活起来的实用路径,顺序的排布会让你有理由一直走下去:
先量一量你已经有的东西。 在改变团队工作方式之前,先针对现有模型算一个漂移评分。它只需要连接一个仓库,而它给你的,是后面每一步都要拿来对照的基线。
从 Container 图开始。 你的服务、它们的技术栈和关键关系。把它定为权威参考,并删掉那些次要的版本,因为两个事实来源等于零个。
将架构转为代码。 将你的模型导出为
archyl.yaml,提交到代码仓库,并设置 CI/CD 同步。添加合规性规则。 从显而易见的那些开始(每个容器写明一项技术、每个容器至少参与一个关系),等团队不再被它们绊倒时再扩展。
将文档纳入 PR 工作流。 一个检查项能起作用。CI 里的一个漂移阈值效果更好,因为它是失败,而不是询问。
设置 MCP Server。 把模型交给你的编码智能体,让读取和更新架构发生在工作的流程之中,而不是工作之后。
看趋势,别看数字。 每月一次就够了。要问的是第 3 到第 6 步是否守住了防线,而唯一能回答这个问题的就是趋势。
活文档架构不是一个终点,它是一种实践。目标不是完美的文档,而是文档足够准确以被信任,并且维护得足够一致以保持这种信任。而评分,就是你弄清自己手上是哪一种的方式。
本系列的其余部分:问题本身以及如何检测,见架构漂移检测;机制部分,见漂移评分是如何计算的。术语定义:活文档、架构漂移。产品页面:漂移检测。第 1 步在 Developer 方案上免费,无需信用卡:archyl.com。