前端知库

技术方案文档怎样写?方案评审时要关注什么?

方案文档先讲清背景、目标和不做什么,再写具体方案,并列出考虑过的备选和放弃的理由;风险和应对、测试计划、灰度与回滚方式、要看哪些指标、排期和分工都要写。评审时重点看目标是否清楚、备选是否真的比较过、出问题时能不能关掉或回滚。

参考答案

本题是回答思路与示例,不对应某个官方规范。示例中的项目和数字只用来演示怎样表达。文中参考的 Kubernetes KEP 和 Rust RFC 是两个开源社区公开的提案模板,各公司的方案模板会有差别。

简答

技术方案文档是动手写代码之前,把“要解决什么、打算怎么做、会有什么风险”写下来给别人看的文档。比如要把老项目的构建工具从 Webpack 换成 Vite,先写方案再评审,比写到一半才发现有插件迁移不了要省事得多。

一份方案通常按这个顺序写:背景和要解决的问题;目标,以及明确不做的事;具体方案;考虑过的备选方案和放弃的理由;风险和应对办法;测试计划;怎样灰度上线、出了问题怎样回滚、看哪些指标决定回滚;最后是排期和分工。

写方案的价值在于让分歧提前暴露。评审的人不只看方案本身对不对,更要看目标是否说得清楚、能不能衡量,备选方案是不是真的比较过,风险有没有对应的办法,上线后出问题能不能快速关掉。

要注意,方案文档是给别人读的,不是写给自己的实现笔记。要写结论和理由,细节放到附录;评审中有争议的地方,按事实和数据讨论,确定以后把结论写回文档里。

每一部分写什么

下面按一份前端方案的常见结构讲,里面的划分参考了 Kubernetes 的 KEP 模板和 Rust 的 RFC 模板,它们都是公开的提案模板。

背景和动机。 讲清楚为什么要做这件事、现在的问题有多严重。KEP 模板要求这里说明这个改动为什么重要、对用户有什么好处。前端方案里最好带上数据,比如“本地冷启动要 90 秒,每次改代码热更新要 5 秒”,而不是只写“构建太慢”。

目标和非目标。 目标要具体、可以衡量,KEP 模板的提法是“要达成什么,怎样知道它成功了”。非目标写这次不做什么,KEP 模板的解释是列出非目标有助于让讨论聚焦。比如“这次只迁移开发环境构建,生产构建下个季度再评估”,评审时就不会有人在生产构建上争半天。

方案。 讲清楚具体怎么做,涉及哪些模块、改哪些接口、数据怎么流转。图比文字更容易让人看懂,关键流程画一张时序图或架构图。

备选方案。 这是最容易写得敷衍的部分。KEP 模板要求写出考虑过的其他做法以及排除它们的理由,Rust 的 RFC 模板也问:为什么这个设计是最好的,考虑过哪些其他设计,不做会有什么影响。每个备选不用写得像主方案那么细,但要能说明白为什么没选。只写一个方案,评审的人没法判断你是比较过才选的,还是只想到了这一个。技术选型怎样讲理由,可以看《面试官问“为什么选这个技术栈”,应该怎样回答技术选型?》。

风险和应对。 风险后面要跟着应对办法,比如“部分 Webpack 插件没有对应的 Vite 插件:先列出全部插件逐个确认,找不到替代的保留旧构建作为兜底”。Rust 的 RFC 模板还有一节专门写缺点,问“为什么不该做这件事”,主动写出来比被评审的人问出来好。

测试计划。 写清楚靠什么证明改完没有破坏原有功能,比如哪些单元测试和端到端测试要跑,哪些页面要人工回归。

灰度、回滚和指标。 KEP 模板在这块问得很细:这个功能能不能在线上开关,开启后能不能回滚,回滚以后会有什么影响,哪些指标应该作为回滚的依据。前端方案也一样,先写怎样灰度,比如先在内部或小比例用户上开启;再写怎样关掉,是用功能开关还是切回旧版本;最后写看哪些指标决定继续还是回滚,比如报错率、白屏率、关键页面的性能指标。灰度和回滚的具体做法可以看《前端怎样做灰度发布和金丝雀发布?出问题怎样回滚?》。

排期和分工。 拆成几个阶段,每个阶段交付什么、谁负责、依赖谁。依赖其他团队的部分要单独标出来,并提前和对方确认。

待解决的问题。 Rust 的 RFC 模板留了一节写“还没解决的问题”。评审前还没想清楚的地方,写出来让大家一起讨论,比假装都想好了更容易得到有用的意见。

评审时关注什么

评审方案和评审代码的道理相通。Google 公开的代码评审规范写道,技术事实和数据优先于个人观点和偏好;软件设计问题几乎从来不只是风格或偏好,要按设计原则来衡量。评审方案时可以按下面几个问题去看:

  • 目标能不能衡量?只写“提升性能”的方案,上线以后没法判断有没有做到。
  • 非目标写了吗?没写的话,评审很容易被拉去讨论这次不打算做的事。
  • 备选方案是真的比较过吗?有没有用原型、压测或者数据来支持取舍?
  • 风险有对应的办法吗?最坏情况下会影响多少用户?
  • 出了问题能不能快速关掉或回滚?要看哪些指标、谁来判断?
  • 排期里有没有留出测试、灰度观察和处理意外的时间?

作为方案作者,评审意见要逐条回复,接受的改进文档,不接受的写明理由。评审会上有争议的地方,可以约定用原型或数据验证后再定,结论写回文档,后来加入的人才知道当时为什么这样做。

面试时怎样讲

面试官问“你写过技术方案吗”,可以选一份自己写过、经历过评审的方案,按“为什么要做、比较了哪些方案、评审中改了什么、上线结果如何”来讲:

去年我负责把管理后台的开发构建从 Webpack 迁到 Vite。背景是项目越来越大,本地冷启动要 90 秒左右,大家改代码等热更新也要好几秒。目标定的是冷启动降到 20 秒以内,非目标是这次不动生产构建,避免影响线上。

方案里比较了三种做法:继续优化 Webpack 配置、迁移到 Vite、迁移到另一个基于 Rust 的构建工具。优化 Webpack 的收益有限;另一个工具当时有两个关键插件没有替代品;Vite 的插件都能找到对应的,所以选了它。

评审时有同事指出,开发和生产用不同的构建工具,可能出现“本地正常、线上有问题”。我们加了一条:每次合并前用生产构建跑一遍端到端测试。上线方式是先让两三个同事试用一周,再全员切换,保留旧配置一个月作为回退。最后冷启动降到了 15 秒左右。

这个回答里有数据、有取舍、有评审带来的改进,也有回退办法,面试官能看出你写方案时考虑过风险,而不是写完就动手。

常见追问

什么样的需求需要写方案文档?

一般是改动大、影响面广、或者有争议的事情,比如换框架或构建工具、改公共组件的接口、涉及多个团队协作的功能。Kubernetes 社区的说法可以参考:可能有争议的、大多数新功能、对现有功能的重大改动,都要走提案流程。很小的改动写一段说明放在合并请求里就够了。

评审时有人强烈反对你的方案怎么办?

先弄清楚对方担心的到底是什么,很多时候反对的是某个具体风险,而不是整个方案。能用数据或原型验证的,约定验证后再定;确实是取舍问题的,把两种选择的代价都写进文档,交给负责人拍板。

方案上线以后,文档还要更新吗?

要。实现过程中改了的设计,要写回文档并注明原因;上线后补上实际结果和指标,和当初的目标对比。这样以后有人接手或者要做类似的事,能看到完整的来龙去脉。