# 客户改主意时，用 ADR 别让争论从头再来

> ADR 拦不住客户改方向，但能把争论收敛成一个问题：上下文变了吗？

原文: https://fdetimes.net/zh/guides/adr-when-client-changes-mind/

设想项目进行到第三个月。客户方新来的一位总监参加会议，问道：“为什么数据是夜间同步？应该做成实时的。”会议室里所有人都看向你。

当初拍板这个设计的人已经调岗，那封旧邮件埋在收件箱的某个角落，你只模糊记得当时有个很充分的理由。

Microsoft Learn 描述的正是这种场景：做了却没有记录的决策很容易被遗忘，结果要么反复争论，要么后来的改动无意中违背了最初的意图。团队要么因为没人能反驳而随大流，要么死守一个谁也记不清理由的决策。

前线部署工程师（FDE）在客户现场工作，人员和需求都可能在项目中途变化，这种场景并不少见。应对它最省事的工具是架构决策记录（ADR），只需要一两页纸。

## ADR 记录的是理由，因为理由最先被遗忘

Michael Nygard 在 2011 年那篇关于记录架构决策的文章中指出，在项目的整个生命周期里，最难追踪的之一就是各项决策背后的动机。他给出了明确的限制：整份文档应控制在一到两页。Martin Fowler 要求更严，建议 ADR 保持简短，通常只有一页。

adr.github.io 的定义是：每份 ADR 记录一项架构决策及其理由，一个项目的全部 ADR 构成它的决策日志。AWS Prescriptive Guidance 对目的说得很直白：避免一遍又一遍地讨论同一个架构话题。

**要点:** 不只记录选了什么，更要记录为什么选：理由才是会被遗忘的部分。

## 三个必备部分，两个常被忽略的细节

按照 AWS 的说法，每份 ADR 至少要包含决策的上下文、决策本身，以及它对项目的后果。上下文还应列出团队考虑过的方案。再加上状态和变更历史，就有了一个能应对客户改主意的框架。

能用的 ADR 和走过场的 ADR，差别在两个细节上。第一是后果部分：要写缺点，不能只写好处。一份满是优点的 ADR 读起来像销售材料，有人提出异议时说服不了任何人。

第二是决策句的写法。要写得肯定，比如“团队采用……”，而不是“应该采用……”。“我们应该用批处理”是在邀请争论；“团队采用批处理”是一项承诺。

## 针对上述场景的 ADR 示例

假设你在为一家保险公司部署一个保单检索 Agent。对方 IT 部门只在午夜到早上 5 点之间开放数据库的只读副本（read replica），因为白天核心系统负载很高。你选择了夜间同步。ADR 大致如下：

```markdown
# ADR-0007：通过夜间批处理将保单同步到搜索索引

## 状态
已接受（经客户 IT 代表确认）

## 上下文
- Agent 需要客户核心系统中的保单数据。
- 客户 IT 只允许在 00:00 至 05:00 之间读取只读副本。
- 主要用户是核保员，他们处理的是前一天的保单。
- 考虑过的方案：
  1. 每晚从只读副本批量同步。
  2. 通过变更数据捕获实现实时同步：客户 IT 暂不允许。
  3. 每次查询都调用核心系统 API：高峰时段有负载风险。
- 如果 IT 启用 CDC，或核保员需要当天的保单，需重新审视本决策。

## 决策
团队采用凌晨 1 点运行的批处理任务，读取只读副本并更新索引。

## 后果
- 好：工作时间内不给核心系统增加负载。
- 坏：白天新建的保单要到第二天早上才能被检索到。
- 坏：如果某天夜里任务失败，数据会再晚一天；需要配置告警。
- 中性：如果 IT 启用 CDC，必须编写新的 ADR。
```

注意上下文的最后一行和后果的最后一行。它们写明了一旦变化就应重新审视决策的条件。正是这两行，让 ADR 从一份备忘录变成了谈判工具。

## 客户改主意时，不要修改旧 ADR

回到第三个月的那场会议。你不必为旧设计辩护，也不必立刻让步。打开 ADR-0007，问一句：IT 现在允许变更数据捕获（CDC）了吗？或者，核保员现在需要当天处理保单了吗？

如果答案是否定的，争论可以很快结束，因为原来的理由依然成立。如果是肯定的，说明上下文确实变了，改变方向是有理由的。这时 Fowler 的规则很严格：已接受的 ADR 绝不重新打开或修改，必须由一份新的 ADR 取代。

具体做法是：为实时方案写一份 ADR-0012，记录新的上下文和变更历史。ADR-0007 的状态改为“已被 ADR-0012 取代”。

Nygard 写道，决策被推翻时，旧记录要保留，只需标记为已被取代。Microsoft Learn 建议把两份记录互相链接，AWS Prescriptive Guidance 则强调要把旧记录留在决策日志中。

六个月后，新加入的人读到这条记录链，就能明白项目经历了哪些步骤，以及为什么。

## ADR 应该放进交接材料

一种干净的做法是把 ADR 和它所描述的代码放在同一个仓库里，放在 `docs/adr/` 目录下，文件按编号命名。对 FDE 来说，最大的好处出现在交接那天：决策日志随代码一起交付，和 README、运维手册（runbook）放在一起，客户的运维团队不必去翻一个他们可能根本没有权限访问的 wiki。

把这个目录当作交接材料的一部分，与安装文档同等对待。运维手册回答的是“这东西怎么跑？”；ADR 回答的是接手者想改动时会问的问题：“为什么要这样做？”

交接会上，花几分钟过一遍所有已接受的 ADR，以及每项决策需要重新审视的触发条件。

每项决策一做出就写 ADR，趁理由在大家脑中还清楚，不要攒到最后一周再一起写。AWS Architecture Blog 建议每份 ADR 只聚焦一项决策。如果标题里出现了“和”，就拆成两个文件。

## 让 ADR 变成废纸的几种错误

最常见的错误是写得太多。一份五页的 ADR 很难有人读完，自然也很难在哪场会议上派上用场。第二种是漏写考虑过的方案：新总监提出实时方案时，你需要证明这个方案已经评估过，以及为什么被否决。

第三种是只列优点，这会让怀疑者有理由质疑整份文档。第四种是改主意时直接修改旧 ADR，抹掉了 ADR 本来要保存的历史。

最后一种是只有工程团队知道 ADR 的存在。“已接受”这个状态，只有在客户方有决策权的人读过并确认之后才有分量。

## 一项值得写进简历的技能

在 FDE 的岗位描述中，技术文档是实打实的工作内容。Tungsten Automation 的 Forward Deployed Engineer 招聘启事中写明，要编写面向具体客户的技术文档和最佳实践，以减少知识流失。ADR 正是做到这一点的具体方式。

所以看招聘启事时，留意关于文档或知识流失的条目，在那里提到这个习惯。作品集里放几份去掉客户信息的 ADR，或者在面试中讲一个用 ADR 化解架构变更提议的故事，比简历上的任何形容词都更有说服力。

客户总会改主意，这是他们的权利。你的工作是让每次改主意的代价只是一页新纸，而不是三周从头开始的争论。

**本周动手试试:**

- 挑出当前项目中争议最大的一项决策，在仓库的 docs/adr/ 目录下为它写一份不超过两页的 ADR。
- 在这份 ADR 中至少写两条坏的后果，并写清楚上下文中哪些条件一旦变化，就需要重新审视这项决策。
- 把 ADR 发给客户方的决策人，请对方书面确认其“已接受”状态。

## 信源

- [Documenting Architecture Decisions](https://www.cognitect.com/blog/2011/11/15/documenting-architecture-decisions)

- [Architecture Decision Record](https://martinfowler.com/bliki/ArchitectureDecisionRecord.html)

- [FAQ about architectural decision records](https://docs.aws.amazon.com/prescriptive-guidance/latest/architectural-decision-records/faq.html)

- [Best practices for using architectural decision records](https://docs.aws.amazon.com/prescriptive-guidance/latest/architectural-decision-records/best-practices.html)

- [Master architecture decision records (ADRs): Best practices for effective decision-making](https://aws.amazon.com/blogs/architecture/master-architecture-decision-records-adrs-best-practices-for-effective-decision-making/)

- [Maintain an architecture decision record (ADR) - Microsoft Azure Well-Architected Framework](https://learn.microsoft.com/en-us/azure/well-architected/architect-role/architecture-decision-record)

- [Architectural Decisions Records (ADRs)](https://adr.github.io/)

- [Forward Deployed Engineer – Churn Prevention (Tungsten Automation)](https://careers.ta.com/companies/tungsten-automation/jobs/85436356-forward-deployed-engineer)
