To ADR 的目标是把架构决策记录成持久、精简的记录,让未来的开发者(以及未来的 Claude)可以直接读到决策原因,而不是从代码里猜测。
用途 它用于在项目开发过程中沉淀架构层面的决策。技能的使用时机是用户说出“create an ADR”“record this decision”之类的请求时,帮助把已做出的决定写成一份简短的 ADR 文件。
门槛:只有三条同时成立才写 ADR
- 难以撤销——日后改变主意需要付出可观代价(迁移、重写、供应商锁定)。
- 脱离上下文会令人意外——未来的读者看到代码会疑惑“为什么当时这么做?”
- 存在真实取舍——确实有其他备选方案,而你是出于特定原因选择了其中一个。 只要缺少任何一条,就应说明并跳过 ADR。容易撤销的决策终将被撤销;显而易见的决策不需要记录;非决策(“我们只能这么做”)不算 ADR。便宜的拒绝可以防止 ADR 泛滥;拿不准时,先拒绝并请用户确认该决策确实满足全部三条。
哪些内容算数
- 架构形态,例如“monorepo”“事件溯源写模型 + 投影读模型”。
- 模块/上下文之间的集成模式,例如“Ordering 与 Billing 通过事件而非同步 HTTP 通信”。
- 带锁定的技术选型:数据库、消息总线、认证提供方、部署目标;不是每个库都写,只写换掉要花一个季度的。
- 边界与归属决策,例如“客户数据归 Customer 所有,其他上下文按 ID 引用”。
- 对显而易见路径的有意偏离,例如“因为 X 而用手写 SQL 而非 ORM”,防止下一位工程师“修正”这一有意选择。
- 代码中看不见的约束,例如“因合规不使用 AWS”“因合作方 SLA 必须 <200ms 响应”。
- 当拒绝理由不明显时记录被否决的备选方案,例如考虑过 GraphQL 但出于微妙原因选了 REST,否则半年后又会有人重新提议。
使用方式(工作流程)
- 验证门槛:用一句话复述决策,并逐条核对三个标准;若不通过,告诉用户哪条不满足并停止。
- 定位 docs/adr/:若已存在,扫描最大的 NNNN-*.md 文件名并递增;若不存在,则到有内容要写时才惰性创建。编号为补零的四位数字(0001、0002……)。
- 起草:按模板写入 docs/adr/NNNN-<kebab-slug>.md。短名应简短、便于搜索(如 postgres-for-write-model,而不是 decision-about-database-choice)。正文格式为标题加 1–3 句话,说明上下文、决定了什么以及为什么;ADR 可以只有一段,价值在于记录做过的决定及原因,而不在于填满各个章节。
- 可选章节:仅在确实增加价值时加入,多数 ADR 不需要。包括 Status frontmatter(proposed | accepted | deprecated | superseded by ADR-NNNN,在决策被重新审视时有用)、Considered Options(仅当被否决的备选值得记住时)、Consequences(仅当存在不明显的下游影响需要指出时)。
- 向用户展示:打印文件路径与渲染后的内容,不自动提交,交由用户自行暂存(符合其 git 规则)。
规则 标题写决策本身,而不是问题,例如“Use Postgres for write model”而非“Which database for write model?”。句子应紧凑、使用现在时,不要含糊其辞,不要写“we are considering”。
示例 通过门槛的好例子:“0003 — Manual SQL instead of an ORM”:查询模式是写密集且以 join 为主的形态,ORM 处理不佳,在探索性验证中遇到了性能悬崖;我们接受样板代码的成本,换取可预测的执行计划与显式事务。考虑过 Prisma 和 Drizzle。 应拒绝的例子:
- “我们决定用 Prettier 做格式化”——一个 PR 就能撤销,不满足“难以撤销”,这不是 ADR,而是一个 .prettierrc,或许再加一行 CLAUDE.md。
- “我们决定写测试”——不满足“脱离上下文会令人意外”,没人会对此感到疑惑。
适用场景与限制 适用于需要长期留存架构决策理由的软件项目,尤其是涉及技术锁定、模块边界、集成方式与有意偏离常规做法的决策。限制在于它有意拒绝大多数日常决策,只记录同时满足三条标准的决策;关于具体模板字段的更多细节、安装方式与平台支持,资料中暂未提供。