---
name: decision-and-rfc
description: 架构决策记录（ADR）、技术提案（RFC）与重大方案论证的表达规范。基于第一性原理、权衡对齐（Trade-offs）与可证伪性。拒绝报喜不报忧，要求显式声明放弃的代价与推翻条件。触发："写方案 / 架构决策 / ADR / RFC / 技术提案 / 选型报告 / 为什么选这个 / 方案对比 / 技术立项 / 重构方案"。
---

# 架构决策记录（ADR）与技术方案（RFC）表达规范

架构与方案的本质是**在冲突的约束中做权衡（Trade-offs）**。没有完美的架构，只有适合当前阶段约束的妥协。

**只写优点、不写代价的技术方案，是不诚实的欺骗。** 一份深度的架构决策，必须清晰交代：**为什么现有机制不可用、选它的代价是什么、放弃了哪些备选方案，以及在什么条件下本方案必须被推翻。**

---

## 零、ADR / RFC 五步骨架（The Decision Skeleton）

动笔撰写任何技术提案、重构方案或架构决策前，按此骨架填空：

```
① 本质矛盾   第一性原理下钻 · 当前物理瓶颈是什么 · 不做该方案的年化代价
② 决策结论   选了什么方案 · 核心架构图 · 数据流与契约约束
③ 权衡矩阵   获得了什么 vs 付出了什么代价 · 引入的新复杂度由什么机制兜底
④ 方案墓碑   考虑过的备选方案 B/C · 在当前什么事实下被否决（防止后人重复讨论）
⑤ 推翻条件   可证伪性 · 当什么指标突破阈值时，本架构必须被推翻重做
```

---

## 一、关键段落表达规范

### 1. 本质矛盾（Problem Definition）
- **先问第一性原理**：问题本质是性能不够、模型能力不足、还是流程设计错误？
- **量化不做该方案的代价**：
  ```text
  ❌ “当前日志记录比较分散，排查问题不太方便，因此需要统一日志中心。”
  ✅ “当前 5 台服务器日志分散在各机本地，跨机事故定位需串行 SSH 查 5 次，平均 MTTR 为 42 分钟；
     上月因日志分散导致的定位超时事故共 3 起，累计中断 114 分钟。”
  ```

### 2. 权衡矩阵与代价显式化（Trade-offs）
- 必须包含专门的小节：**「我们付出了什么代价（Costs & Limitations）」**。
- 交代三件事：
  - **性能/延迟代价**：增加了几毫秒网络延迟？增加了几倍磁盘读写？
  - **心智/学习代价**：团队理解新方案需要多长时间？API 是否破坏既有习惯？
  - **运维兜底代价**：新依赖挂了怎么办？是否有无状态降级预案？

### 3. 弃用方案墓碑区（Rejected Alternatives）
- **防止团队陷入“月经周期式重提旧方案”的内耗**。
- 记录格式：
  ```markdown
  ### 弃用方案：自建 Kafka 消息队列
  - **为什么考虑过**：吞吐量极大，生态成熟。
  - **为什么在当前阶段否决**：
    1. 需至少 3 节点 ZooKeeper/KRaft 集群，每月闲置硬件成本增加 ¥1200+；
    2. 当前系统峰值 QPS 仅为 140，PostgreSQL LISTEN/NOTIFY 或 Redis Stream 完全能承载；
    3. 维护团队只有 1 人，缺乏 Kafka 集群调优与宕机恢复的专职人力。
  ```

### 4. 推翻与失效条件（Termination Conditions）
- 方案必须有**自我消亡的判据**（可证伪性）。
- 示例：
  ```markdown
  ### 本决策推翻条件
  当满足以下任一条件时，本方案视为已触及天花板，应推翻重选分布式方案：
  1. 单表日增行数突破 500 万行，或历史数据归档后总表体积仍超过 100GB；
  2. 跨机事务写延迟 p99 超过 200ms；
  3. 团队规模扩展至 10 人以上，需要强隔离的多租户权限。
  ```

---

## 二、正反案例对比

### ❌ 假人八股方案（报喜不报忧）
> **关于引入 GraphQL 的技术提案**  
> 随着业务发展，传统 RESTful 接口存在过度获取和数据字段冗余的问题。GraphQL 作为业界主流方案，具有按需查询、类型安全、高性能等诸多优势，能够极大提升前后端协作效率，赋能业务快速迭代。经过调研，建议在下一阶段全面推广 GraphQL，替换现有 REST API。

### ✅ 工业级架构决策记录（ADR）
> **ADR-014：保持 RESTful JSON API，拒绝全面引入 GraphQL**  
> 
> **一、决策背景**  
> 移动端与小程序界面改版频繁，存在同个实体在不同视图需不同字段的问题。部分团队提议引入 GraphQL。  
> 
> **二、决策结论**  
> **维持 RESTful API + Sparse Fieldsets（通过 `?fields=id,name` 动态裁剪字段），拒绝引入 GraphQL 全量网关。**  
> 
> **三、权衡与代价分析**  
> - **收益**：避免引入 GraphQL 引擎带来的解析开销（实测单请求 CPU 消耗高 15%）；保留现有基于 Cloudflare CDN 的 URL 级 HTTP 缓存机制；保持 PostgREST/Supabase 原生网关能力。  
> - **代价**：对于复杂的嵌套深度图查询，客户端需要发起 2 次串行请求或依赖 BFF 层专门聚合。该代价通过在现有 Node 服务中增加专门的聚合路由解决。  
> 
> **四、墓碑方案（为什么否决 GraphQL）**  
> 1. CDN 缓存穿透：GraphQL 默认走 POST 请求，天然破坏 Cloudflare 边缘缓存，将所有读请求压回源站；  
> 2. N+1 查询与 DoS 风险：需引入复杂的 DataLoader 和深度限制算法，团队当前缺乏应对恶意嵌套查询的防御经验；  
> 3. 工具链包袱：前端各仓库包体积需额外增加 ~40KB 的 Apollo Client 依赖。  
> 
> **五、推翻判据**  
> 当面向三方开放的 OpenAPI 实体关系嵌套超过 4 层且无法提前枚举视图模式时，方可重新评审 GraphQL 的局部接入。

---

## 三、📋 ADR / RFC 扣分清单（Deduction Rubric）

评审任何架构决策、技术方案或 RFC 前逐条核验，**命中任何一项扣 25 分（满分 100，低于 75 分直接打回重写）**：

| 违规维度 | 扣分项（Anti-pattern） | 扣分 | 为什么致命 | 修正方案 |
|---|---|:---:|---|---|
| **代价隐瞒** | **通篇只讲优点，不写负面代价与引入的新复杂度** | -25 | 世界上没有免费的午餐，隐瞒代价意味着根本没做落地压力测试。 | 必须设立专门章节列出性能损耗、运维心智负担与单点故障风险。 |
| **墓碑缺失** | **没有记录被否决的备选方案与否决事实** | -25 | 评审人无法判断是“深思熟虑的最优选”还是“只知道这一个方案”。 | 明确写出考虑过哪些替代方案，因何种具体的现实约束而放弃。 |
| **推翻盲区** | **没有给出终止与推翻的指标条件** | -25 | 方案变成了永恒真理，技术债务会在业务膨胀后死死锁死系统。 | 设定具体的量化红线（如数据量、QPS、延迟阈值），达到即启动重构。 |
| **虚假量化** | **使用“大幅提升性能/极高扩展性/极其优雅”等主观形容词** | -25 | 毫无工程基准，空洞形容词无法作为事后验收的技术依据。 | 给出实测 Benchmark 数字、延迟压测毫秒数或架构吞吐量计算过程。 |
