RFC 与技术方案写作
这件事为什么重要
很多团队都承认“文档重要”。
但真到做决策时,还是会退回到几种熟悉的方式:
- 开会拍板
- 在聊天群里来回争
- 靠某个熟悉系统的人口头解释
- 方案改来改去,却没人能复述最初为什么这么做
RFC 的价值就在这里。
它不是为了让流程看起来更正规。
它是把模糊讨论变成结构化判断,把“我觉得”变成“我们知道自己在解决什么、承担什么代价、准备怎么落地”。
这也是为什么很多成熟工程团队会保留某种形式的 proposal、design doc、RFC、ADR。
名字可以不同。
本质很接近:
在决策真正进入执行前,先把问题、方案、边界和代价写明白。
先把 RFC 这个词讲清楚
RFC 原本是 Request for Comments。
简单说,它不是“最终定稿”,而是“把一个足够完整、可讨论的提案摆到桌面上”。
这句话里有两个重点:
第一,它不是随手记点子。
第二,它也不是拍板后的公告。
它处在中间那段最关键的区间:
- 问题已经比较清楚
- 方案还需要讨论
- 团队需要围绕同一份材料达成共识
如果把时序再讲得直白一点:
- 想法阶段,通常还是口头讨论、草图、临时笔记
- RFC 阶段,开始进入可评审、可修改、可比较的提案
- 决策后阶段,会沉淀成执行计划、任务拆解、ADR、运行手册或长期文档
所以 RFC 不是“写文档”这么简单。
它更像是一次正式决策前的思考容器。
它解决的不是“有没有文档”,而是“讨论质量”
很多团队文档并不少。
真正缺的是高质量讨论材料。
一个问题在没有被写清楚之前,团队经常会出现这些情况:
- 每个人讨论的其实不是同一个问题
- 方案比较时,评价标准不一致
- 会议里最会说话的人影响最大
- 过一段时间再回看,没人记得当时的 trade-off
一份好的 RFC 至少能把这几件事拉回正轨:
- 问题定义统一
- 备选方案摆在同一张桌子上比较
- 风险不再藏在口头表达里
- 决策背景可以被后来的人追溯
这就是它真正的工程价值。
为什么 senior 工程师特别需要这项能力
因为 senior 的影响力往往不再只来自“自己把代码写出来”。
更多时候,影响力来自:
- 帮团队把问题定义准确
- 在分歧里建立共同语言
- 让复杂决定变得可沟通、可执行、可复盘
如果只会在会议里讲得热闹,却不能把判断沉淀成文档,很多经验都很难真正复用。
所以 RFC 写作不是“表达加分项”。
它已经是工程判断的一部分。
什么时候需要写 RFC,什么时候不需要
这点一定要讲清楚。
不是所有改动都值得写一篇长文档。
如果什么都要求 RFC,团队最后只会讨厌文档。
比较值得写 RFC 的场景通常有这些特征:
- 影响面跨团队或跨系统
- 变更不可逆或回滚成本高
- 有两种以上合理方案,需要比较
- 迁移周期长,需要分阶段推进
- 决策里有明显 trade-off,后续很可能被反复追问
不太需要正式 RFC 的情况也很常见:
- 局部重构,影响边界清楚
- 已经有明确团队共识,只是常规执行
- 风险很低,回滚容易
- 问题本身还没有被定义清楚,先做小实验更合适
换句话说,RFC 不是成熟的象征。
对问题规模的判断,才是成熟的象征。
一份好 RFC 最先要解决什么
不是展示作者懂多少。
而是回答四个问题:
- 我们到底在解决什么问题?
- 为什么是现在解决?
- 为什么是这个方案,而不是别的方案?
- 这个决定会给执行、运行和未来演进带来什么后果?
如果这四个问题没回答清楚,图画得再漂亮,文档也还是空的。
文档最容易写偏的地方:方案写得太快,问题写得太少
这是最常见的问题。
很多工程师一动笔就写:
- 新架构怎么搭
- 新模块怎么拆
- 新 API 长什么样
结果读者看完会问:
“所以我们为什么要做这件事?”
这说明问题定义没有站住。
成熟的 RFC 往往会把不少篇幅放在问题本身:
- 现状是怎样的
- 痛点是什么
- 痛点的证据是什么
- 受影响的是谁
- 不处理的后果是什么
这不是绕远路。
这是给后面的方案比较提供地基。
问题定义怎么写,才不至于空
一个常见误区是写成泛泛口号:
- 系统复杂度高
- 开发效率低
- 性能不够好
- 维护成本高
这些都不算真正的问题定义。
它们更像是情绪化标签。
更可用的写法应该尽量具体:
- 哪类页面在什么条件下性能差
- 哪个链路的发布经常出事故
- 哪类需求每次都要重复造轮子
- 哪些团队协作点经常因为边界不清而返工
当问题被写成可以被观察、被验证的事实,后面的讨论才会落地。
一个实用的 RFC 骨架
不同团队模板会不一样,但核心部分通常离不开这些:
1. 摘要
用一段话说明:
- 提案是什么
- 解决什么问题
- 预期收益是什么
- 这次评审需要大家关注什么
摘要不是“全文缩写”。
它更像给读者一个入口。
2. 背景与问题定义
这里要说明:
- 现状
- 业务与工程背景
- 明确的痛点
- 已知约束
如果有数据、事故记录、用户反馈、性能观测,应该尽量带上。
3. 目标与非目标
这是极容易被省略、但非常值钱的部分。
目标告诉团队“这次一定要解决什么”。
非目标告诉团队“这次不解决什么”。
没有非目标,讨论很容易无限膨胀。
4. 方案设计
这里才开始写方案。
应包括:
- 整体思路
- 关键流程
- 接口与数据边界
- 兼容性
- 安全、性能、运维影响
5. 备选方案
很多文档这一节只是形式化凑数。
真正有价值的备选方案不是列出“明显不行的方案”来衬托主方案。
而是把当时真正可能选择的路线摆出来比较。
6. 迁移与发布计划
如果方案需要上线落地,就不能只写“后续逐步推进”。
需要明确:
- 分几阶段
- 怎么灰度
- 怎么回滚
- 如何验证
- 谁负责哪些部分
7. 风险与开放问题
成熟文档不会假装所有事情都确定了。
把不确定性显式写出来,反而会提高讨论质量。
ADR、design doc、RFC 之间是什么关系
很多团队会纠结命名。
其实不必过度神圣化。
可以把它们理解成偏重点不同:
- RFC 更强调“提案待评审”
- design doc 更强调“设计细节与实施说明”
- ADR 更强调“记录已经做出的关键架构决策”
在实践里,它们可以串起来:
- 先写 RFC 讨论方向
- 方案收敛后补 design doc
- 最终关键结论沉淀成 ADR
也有团队把这些合并成一种统一模板。
这没问题。
关键不是名字。
关键是文档是否真的承载了决策过程。
好文档的核心不是“全”,而是“让读者能判断”
很多工程师写文档时会掉进两个极端:
- 太短,只有结论,没有推理
- 太长,堆满细节,看不到重点
真正好的技术方案文档,不一定最厚。
但它会让读者抓到几件关键事:
- 背景是什么
- 作者的判断链路是什么
- 哪些地方已经想清楚
- 哪些地方仍然存在风险
- 现在需要评审者做什么
如果读者读完还是没法判断,那文档就没有真正完成它的工作。
什么叫“诚实地写 trade-off”
这也是 senior 感很强的一部分。
很多方案文档会把主方案写成“全面占优”。
现实里很少有这种情况。
真正可信的文档会明确承认:
- 这个方案在 A 上更好
- 在 B 上会付出额外成本
- 团队选择它,是因为当前约束更重视 A
比如:
- 更强的一致性,可能换来更高的实现复杂度
- 更低的运行成本,可能换来更高的迁移成本
- 更灵活的扩展性,可能换来更陡的学习曲线
把这些写出来,不会显得方案不稳。
恰恰相反。
这会让评审者更相信作者知道自己在做什么。
数据、样例和图示为什么重要
工程文档不是文学作品。
很多判断如果没有具体材料支撑,会显得很飘。
常见的有效材料包括:
- 请求量、错误率、性能数据
- 一个典型时序图
- 关键接口样例
- 当前实现与目标实现的对照
- 迁移阶段的边界图
但也要避免另一个极端:
为了显得专业,塞进一堆图和表。
图示不是装饰。
它应该帮助读者更快理解结构和边界。
读者意识:你写给谁看,决定你怎么写
同一份 RFC,常见读者可能包括:
- 同组工程师
- 上下游团队
- 技术负责人
- 测试、运维、产品
这意味着文档不应该只对作者自己友好。
比较稳妥的写法通常是:
- 主叙事尽量讲清业务背景和工程问题
- 细节留在具体小节或附录
- 关键术语第一次出现时给一句解释
不是所有人都需要读到最底层实现。
但所有相关方都应该能理解“这次变更会对自己有什么影响”。
评审流程怎么设计,才能减少空转
很多团队写 RFC 不难,真正难的是评审机制。
常见失败方式有三种:
- 没有人真正阅读,只在会议里即兴讨论
- 评论很多,但没有人负责收敛结论
- 文档通过了,执行却没人跟进
一个更实用的评审流程通常包括:
1. 小范围预热
先找最关键的几位同事看一版。
目的是尽早发现大方向是否站得住,而不是正式盖章。
2. 异步评论
让大家围绕同一份文本提问、指出风险、补背景。
异步评论的好处是:
- 讨论更可追溯
- 不被会议时间限制
- 思考更完整
3. 同步收敛
如果争议点比较大,再开会。
会议的目标不应该是“第一次看文档”。
而应该是“围绕已暴露的分歧做收敛”。
4. 决策记录
接受、拒绝、延期、补充验证,都应该明确写回文档。
否则过一阵子,大家又会从头争一遍。
评论怎么写才有用
无论你是作者还是评审者,都需要区分评论类型。
常见类型包括:
- 事实纠正
- 风险提醒
- 备选方案
- 范围控制
- 纯编辑性建议
这很重要。
因为不是所有评论都应该阻塞文档前进。
比较成熟的做法是显式标记:
- blocking
- non-blocking
- question
- suggestion
这样讨论会清楚很多。
一个成熟作者在评审里应该怎样表现
不是死守主方案。
也不是谁提意见就立刻全改。
更好的状态是:
- 愿意解释判断依据
- 愿意承认没有想清楚的地方
- 愿意在关键分歧上补实验或补数据
- 能把评论吸收进文档,而不是散落在聊天记录里
这也是为什么文档能力和领导力能力经常绑在一起。
因为它们都在处理同一件事:
如何让多人围绕复杂问题建立共同理解。
常见失败模式
1. 把 RFC 写成产品宣传页
只写好处,不写风险。
这类文档读起来顺,但不可信。
2. 把 RFC 写成实现细节堆叠
读者看完知道每个函数怎么写,却不知道为什么选这个方向。
3. 备选方案形同虚设
如果备选方案都是“明显不成熟”“明显不适合”,那这一节就失去意义了。
4. 范围无限膨胀
没有目标和非目标,评论一多,文档就会越来越像重写整个系统。
5. 通过后没人维护
文档接受了,但执行现实发生变化,文档却不再更新,最后反而误导后来的人。
RFC 和代码之间的关系
文档不是代码的替代品。
但它也不只是代码的附庸。
可以这样理解:
- RFC 决定大的结构和边界
- 代码实现把它具体化
- 回头看代码时,RFC 解释了“为什么不是另一种写法”
当系统进入长期维护阶段,这个“为什么”非常值钱。
因为很多复杂决策不是从代码里自然显现出来的。
适合练表达的点
这类主题很适合做表达训练,因为它天然要求你把抽象判断说清楚。
尤其值得练的点包括:
- 怎么区分问题和方案
- 怎么解释 trade-off
- 怎么说明目标与非目标
- 怎么说清“为什么现在做”
- 怎么把技术结论和组织现实连起来
如果一个工程师能把这些讲清楚,往往说明他已经不只是在做局部实现。
一个可以直接用的 RFC 写作框架
下面这个框架不是唯一标准。
但在多数工程团队里都足够实用。
标题
标题要具体。
例如:
- “统一前端缓存失效策略”
- “将图片处理链路迁移到边缘运行时”
不要写成:
- “架构优化方案”
- “系统升级提案”
摘要
三到六句话即可。
把问题、方案和预期收益说清楚。
背景
描述现状和约束。
目标
列出必须达成的结果。
非目标
明确这次不处理的边界。
方案
给出结构、接口、流程、发布策略。
备选方案
至少写出当时真正有竞争力的替代路线。
风险
把性能、兼容性、运行稳定性、团队学习成本等都摆出来。
验证计划
说明如何通过实验、灰度、监控来判断方案是否成立。
决策记录
记录接受、拒绝、修改和后续 action item。
中国互联网语境下,RFC 经常会卡在哪里
在很多节奏很快、业务压力很重的团队里,大家并不是不知道文档重要。
更常见的问题是:
- 时间被排期压缩
- 需求变化太快
- 决策更依赖少数熟悉业务的人
- 组织习惯同步会议多于异步评审
所以在国内语境里,推动 RFC 往往不能走“形式先行”路线。
更现实的做法通常是:
- 先从跨团队、高风险决策开始
- 模板尽量轻,不一上来就写成论文
- 评审关注执行价值,而不是格式完整度
这样更容易活下来。
海外互联网语境下,为什么 design doc / RFC 传统更强
很多海外工程团队长期依赖异步协作。
团队分布、时区协作、书面文化、公共 API 稳定性要求,都会推动文档体系更成熟。
这也是为什么你会在 Google、Rust、React、Go 这些生态里看到更明确的 proposal 或 RFC 传统。
文档在这些环境里不只是补充说明。
它本身就是协作接口。
这一题在面试或分享里怎么讲更像 senior
不要上来背模板。
更好的讲法是:
先说明 RFC 解决的是讨论质量和决策可追溯性问题。
然后再说:
- 什么场景值得写
- 一份好文档最重要的是问题定义和 trade-off
- 怎么组织评审
- 怎么让文档进入执行闭环
这样听起来会更像你真的用过它,而不是只是看过模板。
练习建议
练习 1:把一次真实争议写成短 RFC
练什么:
把口头分歧转成结构化文档。
最小交付物:
一篇 2 到 4 页的内部提案。
验收标准:
- 能清楚复述问题
- 有至少两个真实备选方案
- 有明确的目标和非目标
常见误区:
- 只写结论
- 把备选方案写成陪跑
练习 2:给一篇旧设计文档补 ADR
练什么:
把决策结果从执行细节里抽出来。
最小交付物:
一页 ADR。
验收标准:
- 能回答为什么做这个决定
- 能说明当时放弃了什么
常见误区:
- 把 ADR 写成实现摘要
练习 3:做一次评审收敛记录
练什么:
训练把评论区的分歧真正收拢。
最小交付物:
一次文档评审结论更新。
验收标准:
- 评论被归类
- 决策状态明确
- 后续动作清楚
常见误区:
- 评论很多,但没有最终结论