用途
该技能的核心主张是:记录决策,而不仅是代码。最有价值的文档捕捉的是“为什么”——导致某个决策的背景、约束与权衡。代码展示构建了什么,文档解释为何这样构建以及考虑过哪些替代方案。这些背景对后续在代码库中工作的人和智能体都至关重要。
何时使用
- 做出重大架构决策
- 在相互竞争的方案之间选择
- 新增或变更公共 API
- 发布改变用户可见行为的功能
- 让新团队成员(或智能体)熟悉项目
- 发现自己反复解释同一件事
不适用场景:不要为显而易见的代码写文档;不要添加只是复述代码的注释;不要为一次性原型写文档。
架构决策记录(ADR)
ADR 捕捉重大技术决策背后的推理,是价值最高的文档。
何时编写 ADR
- 选择框架、库或重大依赖
- 设计数据模型或数据库模式
- 选择认证策略
- 决定 API 架构(REST vs. GraphQL vs. tRPC)
- 在构建工具、托管平台或基础设施之间选择
- 任何撤销成本高昂的决策
优先匹配既有约定
创建 ADR 前,先检查仓库中是否已有既定约定——现有 ADR、项目说明以及 ADR 相关配置或工具(例如 .adr-dir 文件)。既有约定优先于默认模板。需要匹配:
- 位置与格式——例如 docs/adr/.md、Documentation/Decisions/.rst、MADR 布局或 adr-tools 设置。匹配现有目录、文件扩展名和标记语言(Markdown vs reStructuredText)。
- 编号与命名——延续现有序列和文件名模式(ADR-004-Title.rst、0004-title.md 等);不要从 001 重新开始或引入第二套方案。
- 章节标题——复用项目的标题集合,而非强加本模板的标题。
若证据存在冲突,应指出冲突,而不是悄悄引入另一套方案。只有在无法确定任何约定时,才应用默认模板。
ADR 模板
默认将 ADR 存放在 docs/decisions/ 并按顺序编号(除非项目已使用其他位置)。模板包含以下章节:
- 标题:如 # ADR-001: Use PostgreSQL for primary database
- Status:Proposed | Accepted | Superseded by ADR-XXX | Deprecated
- Date:日期
- Context:背景与关键需求
- Decision:决策内容
- Alternatives Considered:考虑过的替代方案及其利弊与拒绝原因
- Consequences:后果与影响
ADR 生命周期
PROPOSED → ACCEPTED → (SUPERSEDED 或 DEPRECATED)
不要删除旧 ADR,它们承载历史背景。当决策变化时,编写新 ADR 引用并取代旧 ADR。
内联文档
何时注释
注释“为什么”,而非“是什么”。例如,说明限流使用滑动窗口、在窗口边界重置计数器而非固定计划,以防止窗口边缘的突发攻击。
何时不注释
- 不要注释自解释的代码
- 不要留下本应现在完成的 TODO 注释
- 不要留下被注释掉的代码(git 有历史记录)
记录已知陷阱
对非显而易见的约束用文档说明,例如某函数必须在首次渲染前调用,否则会导致无样式内容闪烁,并引用相关 ADR 获取完整设计理由。
API 文档
针对公共 API(REST、GraphQL、库接口):
- 内联类型(TypeScript 首选):使用 JSDoc 风格注释说明参数、返回值、抛出的异常和示例。
- REST API 使用 OpenAPI / Swagger:描述路径、请求体、响应码等。
README 结构
每个项目都应有 README,涵盖:
- 项目名称与一段话描述
- Quick Start:克隆仓库、安装依赖、设置环境、运行开发服务器
- Commands:命令表格(如 npm run dev、npm test、npm run build、npm run lint)
- Architecture:项目结构与关键设计决策的简要概述,并链接到 ADR
- Contributing:如何贡献、编码标准、PR 流程
变更日志维护
针对已发布功能,按版本记录 Added、Fixed、Changed 等条目。
面向智能体的文档
针对 AI 智能体上下文的特别考虑:
- CLAUDE.md / rules 文件——记录项目约定,让智能体遵循
- Spec 文件——保持规格更新,让智能体构建正确的东西
- ADR——帮助智能体理解过去决策的原因(防止重新决策)
- 内联陷阱——防止智能体落入已知陷阱
文字审阅
检查技术内容后,为使用者审阅文字。更清晰的措辞不得改变决策或其限制。
- 标记编辑后必须保留的细节:名称、数字与单位、命令、路径、链接、条件、权衡和不确定性。对照可用代码与决策背景核查,标记无法证实的内容。
- 用读者需要的具体信息替换套话式引言、宣传性形容词和重复总结。不要用编造的示例或更强的保证替换无依据的声明。保留必要的技术重复和项目既定术语。
- 将编辑后的文档与原文及其来源对比。恢复任何丢失的限定词或注意事项,验证命令和代码示例仍如文档所述可用,并解释任何未解决的事实问题,而不是将其粉饰掉。
常见合理化与反驳
- “代码是自文档化的”:代码展示“是什么”,不展示“为什么”、被拒绝的替代方案或适用约束。
- “等 API 稳定了再写文档”:写文档会让 API 更快稳定,文档是设计的第一次测试。
- “没人读文档”:智能体会读,未来的工程师会读,三个月后的自己也会读。
- “ADR 是额外负担”:10 分钟的 ADR 可避免六个月后关于同一决策的 2 小时争论。
- “注释会过时”:关于“为什么”的注释是稳定的;关于“是什么”的注释会过时——这正是只写前者的原因。
危险信号
- 架构决策没有书面理由
- 公共 API 没有文档或类型
- README 未说明如何运行项目
- 用注释掉代码代替删除
- 已存在数周的 TODO 注释
- 有重大架构选择的项目却没有 ADR
- 文档复述代码而非解释意图
验证清单
记录文档后:
- 所有重大架构决策都有 ADR
- README 涵盖快速开始、命令和架构概述
- API 函数有参数和返回类型文档
- 已知陷阱在相关位置内联记录
- 没有残留的被注释代码
- Rules 文件(CLAUDE.md 等)保持最新且准确
- 文字编辑保留来源细节、决策权衡和限定词,且不添加无依据的保证