ADR 格式
ADR 放在 docs/adr/,按顺序编号:0001-slug.md、0002-slug.md,依此类推。
docs/adr/ 目录按需创建:需要第一份 ADR 时才建。
模板
就这些。一份 ADR 可以只有一段。价值在于记下做过这个决定、为什么,而不在于把各节填满。
可选的节
只在真有价值时才加。大多数 ADR 用不上。
- Status frontmatter(
proposed | accepted | deprecated | superseded by ADR-NNNN):决策会被重新审视时有用 - Considered Options(考虑过的选项):只在被否掉的备选值得记住时
- Consequences(后果):只在需要点出不明显的下游影响时
编号
扫一遍 docs/adr/,找到现有的最大编号,加一。
什么时候提出写 ADR
下面三条必须全部成立:
- 难以回退:日后改主意的代价不小
- 缺了上下文会让人意外:未来的读者看着代码会纳闷「他们到底为什么这么做?」
- 真实取舍的结果:确实有别的选项,出于具体理由选了其中一个
决策容易回退,就跳过:回退就是了。不让人意外,就没人会问为什么。没有真正的备选,除了「做了显而易见的事」也没什么可记。
哪些够格
- 架构形态。「我们用 monorepo。」「写模型用事件溯源,读模型投影进 Postgres。」
- 上下文之间的集成方式。「Ordering 和 Billing 之间走领域事件,不走同步 HTTP。」
- 带锁定效应的技术选型。 数据库、消息总线、认证服务商、部署目标。不是每个库都算:只算那些换掉要花一个季度的。
- 边界与范围的决定。「客户数据归 Customer 上下文所有;其他上下文只按 ID 引用。」明确说「不」的决定和说「是」的一样有价值。
- 有意偏离显而易见的路。「我们手写 SQL、不用 ORM,因为 X。」凡是讲道理的读者会默认相反做法的地方都算。这类记录能拦住下一个工程师把有意为之的东西「修」掉。
- 代码里看不到的约束。「合规要求不允许用 AWS。」「响应时间必须低于 200ms,因为合作方的 API 合同这么规定。」
- 否掉的备选,当否掉的理由不明显时。 考虑过 GraphQL、出于微妙的原因选了 REST,就记下来;不然半年后又会有人提 GraphQL。