专业书籍精读 · Accelerate · 第 4 章
Accelerate: The Science of Lean Software and DevOps · Ch 4 · Forsgren, Humble & Kim · 2018
你手机里的 App,有的一周更新好几次,有的半年才动一次。《Accelerate》(中译《加速》)前三章用数据证明了一件事:软件发得又快又稳的团队,公司业绩也更好。但它们没回答最要紧的那个问题——那我们星期一早上到底该做什么不一样的事?第 4 章就是来回答它的:哪些具体的技术做法,真的能把「又快又稳」做出来。
按常识,改动发得越勤,出错的机会应该越多。可数据是反的:一天发好几次的团队,出事反而更少、修得也更快。攒三个月发一次大版本的那种团队,才是通宵、回滚、互相甩锅的常客。这一章要解释这个怪事从哪来。
想象三个人各自装修同一间屋子,各干各的、三个月不碰面,最后一天才开门对照——一个人把承重墙砸了,另一个人正好在那面墙上挂了柜子。那天注定是灾难,而且没人说得清是谁先动的手。
攒大版本就是这么回事:几百处改动混成一坨进生产,出了问题只能一处处翻。真正让人痛的不是「改动多」,而是「改动堆在一起、太晚才见面」。
一、一切都记账。不只是代码,连「这台机器是怎么装的、参数设成多少」都写下来、存进公共档案库。好处是:机器烧了,照着档案重装一台一模一样的,而不是靠某个老员工的记忆。这一章有个挺意外的发现——代码存档案库现在人人都做了,真正拉开差距的是「机器和配置也一起存」。
二、天天碰头。别各改各的三个月,每人每天下班前,把自己那份活并回大家共用的那一份。今天的冲突今天解决,小到几分钟就能弄完。还是那间屋子——改成每天收工前互相看一眼,灾难就没机会攒出来。
三、让机器当质检员。每改一次,就自动把全套检查跑一遍。关键不在「有没有这套检查」,而在信不信得过:它说没事,你就真敢发;它报警,你就知道是真出事了。这里还藏着一个更意外的发现——这套检查最好由写代码的人自己写。数据显示,甩给专职测试团队或者外包去写的那种,对交付效能几乎没有帮助。原因也不难懂:只有写代码的人知道自己哪里脆;也只有他自己写,才会顺手把代码改成好测的样子。
最反直觉的收获不在速度,而在人。做到这几件事的团队,加班更少、倦怠更轻、发布日不再是恐怖之夜,团队之间的信息也更通畅。而气氛一好,大家更愿意继续坚持这些做法——它就转起来了。所以这一章真正的主张是:这些技术实践不只是提效工具,它们会实实在在改变一个组织里人的状态。
持续交付不是买一套流水线,而是让大家共用的那份代码随时都能发出去:一切进档案库、每天并回主干、让信得过的自动检查替你把关。而整套东西的命门只有一个——自动检查一旦老是误报,人就会开始无视它,前面所有投入全都白搭。
想进到具体机制、研究结论和示意图? → 切到精读版
《Accelerate》第 4 章从「测什么」转向「做什么」:它把持续交付(continuous delivery)这个大词拆成一组可测量、可勾选的技术能力——全面配置管理、持续集成、主干开发、测试自动化与测试数据管理——并用统计证据说明这些能力驱动交付效能与组织绩效。更反直觉的是,它们同时降低倦怠与部署痛苦、改善组织文化,与文化互为因果地转成一个良性循环。
本章是 Part I「研究发现」的第 4 章:上承第 2 章(四个关键指标把「交付效能」变成可测的结果)与第 3 章(Westrum 模型把「文化」变成可测的量表),下启第 5 章(架构)与第 6 章(把安全融入交付)。前三章解决的是「怎么知道自己行不行」,这一章第一次回答「那到底该动手做什么」——它也是后来 DORA「能力模型」(capabilities)的直接源头。
前三章已经把结论摆在那儿了:快与稳同向、效能可测、文化可测。但一个技术负责人合上书,仍然不知道星期一早上该改什么。持续交付是个人人都在说的词,可「我们在做 CD」这句话几乎不含信息量——有流水线就算吗?有 CI 服务器就算吗?
不把它拆开会怎样?转型就会退化成三种常见的空转:买工具(装了 Jenkins,主干照样天天红着没人管)、设 KPI(要求「每周部署一次」,团队就把十个改动攒成一次部署交差)、爬成熟度等级(第 1 章已经否掉的做法——按模板逐级打勾,与结果无关)。钱花了、会开了、指标不动。
所以这一章要干两件事:第一,把 CD 拆成一条条能测量、能被改的具体能力;第二,用数据回答「值不值」——因为 CD 有真实成本(要写要养自动化测试、要把团队熟悉的长命分支流程拆掉、要重做环境管理),如果它只换来一点点速度,多数组织不会为它掏钱。本章给出的答案是:它换来的远不止速度。
作者先给 CD 下了一个以结果定义的定义,而不是以工具定义。要说自己在做 CD,得同时做到两件事:
支撑它的是《持续交付》一书的五条原则:把质量内建(build quality in)、小批量工作、让计算机做重复的事而人去解决问题、持续改进、人人共担责任。以及三块地基:全面的配置管理、持续集成、持续测试。本章的贡献在于——把这些原则往下落成了一组能在问卷里被度量、并被统计检验的具体能力。
配置管理这一项,问卷问的是四类东西是否都在版本控制里:应用代码、系统配置(机器怎么装、装了什么)、应用配置(各环境的参数、开关)、以及构建与配置脚本。判据很硬:能不能只凭版本库里的东西,把一套环境从零重建出来——不靠某位老员工的记忆,也不靠一台「谁都不敢重启」的祖传机器。
这里有本章第一个反直觉发现:把系统配置和应用配置放进版本控制,与交付效能的相关性比把应用代码放进版本控制更高。听着荒唐——代码入库不是天经地义吗?正因为天经地义:代码入库几乎人人都做了,这一项没有区分度;真正把团队拉开的,是那些常年散落在 Wiki、工单和运维脑子里的东西有没有被同等对待。这也解释了为什么后来「基础设施即代码」会成为独立的一门实践。
CI 的要求是:每次提交都触发一次构建加一轮自动化测试;构建失败是全组最高优先级,修好之前不允许在红着的主干上继续堆新东西。它的产出物很朴素——一份随时可编译、可测试的共用代码。
主干开发是 CI 的前提条件,本章给了它三条可操作的判据(后来被 DORA 沿用):
请注意它不是「禁止分支」。拉一条特性分支、当天并回主干,完全符合;被数据判为有害的是长命分支。为什么长命分支这么贵?因为合并冲突的规模大致正比于「你改的面积 × 别人改的面积」——两边都随时间线性增长,冲突就随时间平方级增长。一天不并,冲突是几行;三个月不并,就是一场需要专人协调的集成战役,而且冲突解到最后没人还记得当初为什么那么改。小批量的真正作用,是把这条平方曲线摁回近乎线性。
这是全章最有价值、也最常被误引的一节。研究没有停在「有没有自动化测试」——那个问题几乎人人都答「有」。它拆出了三个更细的条件,而这三条才是真正的分水岭:
关于最后这条,本章给了一个让很多组织不舒服的发现:主要由 QA 团队或外包方创建、维护的自动化测试,与交付效能没有相关性。注意这话的分寸——是「没有带来交付效能的提升」,不是「有害」,也不是「不需要测试专业人员」。为什么会这样?三条机制都说得通:其一,可测性是设计出来的,开发者不写测试就不会为可测性去改代码结构;其二,反馈回路断了,测试挂在另一个团队手里,红灯到不了能修它的人手上;其三,测试沦为过关仪式——为通过关卡而写,而不是为发现设计缺陷而写。
与之配套的是测试数据管理:能按需拿到跑测试所需的数据、测试数据不成为跑测试的约束、不必为准备数据做大量手工。这一项常被忽视,却往往是「我们的验收测试只能夜里跑一次」的真实原因。
如果本章只证明了「CD 让你发得更快」,它不过是《持续交付》一书的实证附录。它更重的一击在于:持续交付同时预测了一组和「人」有关的结果——更强的组织认同感(愿意说「我们公司」)、更低的部署痛苦(发布前不必焦虑、加班、祈祷)、更低的倦怠,以及更偏向生成型(generative)的 Westrum 文化。
并且这条链是双向的:技术实践改善文化,而更好的文化又让团队更能坚持这些技术实践。第 3 章说文化难改,这一章给出了改它的抓手——不必先开动员会改人心,先把主干打通、把测试修可靠,文化的读数自己会动。这是全书最实用的一条因果主张。
本章的实践听起来都「显然该做」,但每一条都有真实代价。选型的关键不是「要不要做」,而是在你的约束下先做哪一条、先付哪笔账。
表 1 · 长命特性分支(GitFlow 式)vs 主干开发
| 长命特性分支 | 主干开发 | |
|---|---|---|
| 集成频率 | 数周到数月一次,期末集中合并 | 每人每天至少一次并回主干 |
| 冲突成本 | 随分歧时间超线性上涨,末期需专人协调 | 每次都小到当场解决 |
| 反馈延迟 | 「这两个改动不兼容」要几周后才发现 | 数分钟到数小时 |
| 发未完成的功能 | 靠分支天然隔离,不必额外机制 | 必须上特性开关(feature flag)或做增量式设计——这是真实的额外工程投入 |
| 对测试的要求 | 可以靠人工回归撑一阵 | 硬依赖可靠的自动化测试:主干随时可发,没有测试兜底就是裸奔 |
| 代码评审 | 大 PR、评审质量低、走过场 | 小 PR,评审快;但要求团队真的能当天合掉 |
| 适用 | 开源项目(贡献者不可信、异步协作)、需要长期维护多个已发版本的产品 | 同一团队共同拥有一份代码、能持续发布的服务型系统 |
| 诚实的代价 | 集成期与「大爆炸合并」是可预期的灾难 | 特性开关会累积成技术债,需要定期清理;纪律一松就退化成「主干长期红着」 |
表 2 · 自动化测试:谁写、写在哪一层
| 做法 | 本章的结论 | 机制 / 代价 |
|---|---|---|
| 开发者写并维护验收测试 | 与高交付效能相关 | 写的人知道哪里脆,会顺手把代码改成可测的;代价是占用特性开发时间 |
| QA 团队或外包写并维护 | 与交付效能不相关 | 不是「有害」,而是没带来提升:可测性没人设计、红灯到不了能修的人手上 |
| 测试可靠(绿就敢发、红就是真缺陷) | 是整套自动化的前提条件 | 不稳定测试要持续投人清理——这是一笔永远付不完的维护税 |
| 开发者能在本机复现、快速跑 | 必要条件 | 需要测试数据按需可得、环境能从版本库重建 |
| 只靠人工回归 / 上线前集中测 | 与低效能相伴 | 批量被迫变大 → 前置时间变长 → 出事更难定位,形成正反馈 |
表 3 · 把本章原则落到不同交付约束(应用推论,原书未逐一枚举各类形态)
| 发布形态 | 典型场景 | 本章原则怎么落 |
|---|---|---|
| 连续 / 准连续推送 | 服务端 Web 与后端服务,一天数次到数十次 | 主干即可发;靠自动化测试 + 分级放量 + 快速回滚兜底 |
| 发布列车(release train) | 移动端 App、浏览器:受应用商店或用户升级节奏约束,每 2–4 周一班车 | 主干仍然每天合,只是到点从主干切一条短期发布分支——TBD 与发布分支并不冲突 |
| 客户本地部署 | 需长期维护多个已发版本的企业软件 | 必须留维护分支,但把「攒功能」与「维护老版本」分清:前者仍走主干 |
一条实用的排序建议:如果只能先做一件事,先修测试的可靠性。主干开发、每日部署、快速回滚——所有其他实践都要靠「绿灯可信」这块地基站住;地基不稳的时候强推每日合并,只会让主干长期红着,然后团队集体退回长命分支。
这一章之所以影响巨大,是因为它把一堆此前只是「资深工程师的经验之谈」的实践,第一次放进了统计框架里检验。今天你在任何一家公司听到的标准答案——一切进 Git(包括基础设施即代码)、每次提交跑流水线、小 PR 当天合、特性开关解耦发布与部署、自动化测试由写代码的人负责——都能追溯到本章。它也是后来 DORA 那张「能力地图」的直接源头:如今 DORA 把这些整理成可查的能力条目并持续更新,成为团队自评的公共参照。
面试里那个万金油问题「你们怎么发布」,本章给的正是评分标准:主干能不能随时发?分支活多久?谁写验收测试?测试红了当天修吗?环境能不能从版本库重建?——答不上来的,就是还在攒大版本。
10 亿 个文件、约 20 亿行代码、3500 万次提交,而它实行主干开发——除少量发布分支外几乎没有分支,所有新代码直接并入主干。这是主干开发在极端规模下可行的最强反例证据(对「代码多了必须用长命分支」的常见说法)。Potvin & Levenberg《Why Google Stores Billions of Lines of Code in a Single Repository》, CACM 2016 ↗1000+ 个改动,周发布一度累积到 10000 个改动,「协调和交付这么大一次发布所需的人工,已经不可持续」,因此 2016 年 4 月转为从主干准连续推送——每隔几小时推送几十到几百个改动、分级放量到全量。这正是本章「小批量 + 保持主干可发」的工业级验证。Meta Engineering「Rapid release at massive scale」, 2017 ↗12 个月内被用于5000 万次部署(开发、测试与生产环境合计),平均每秒超过一次——部署自动化能把「部署」彻底降格为非事件。W. Vogels「The Story of Apollo — Amazon's Deployment Engine」, All Things Distributed, 2014 ↗16% 的测试存在某种程度的不稳定,全量测试运行中持续约 1.5% 报出 flaky 结果。连 Google 都要长期投入专门机制去压制它——这印证了本章「测试必须可靠」不是一句轻飘飘的要求,而是一笔要一直付的账。Google Testing Blog「Flaky Tests at Google and How We Mitigate Them」, 2016 ↗① 一句话:本章把持续交付从口号拆成可测量的技术能力,并证明它驱动交付效能、组织绩效,还顺带改善文化与人的状态。
② CD 的两个定义性成果:软件始终处于可部署状态(保持可部署优先于做新功能),人人都能快速拿到质量与可部署性的反馈。
③ 五原则:质量内建、小批量、机器做重复的事、持续改进、人人负责;三块地基:全面配置管理、持续集成、持续测试。
④ 配置管理的反直觉发现:系统配置与应用配置入版本控制,比应用代码入版本控制更能区分效能——因为代码入库人人都做了,环境能否从版本库重建才是分水岭。
⑤ 主干开发的三条硬判据:活跃分支 < 3 条、分支寿命 < 1 天、无代码冻结 / 集成期。反对的是分支寿命而非分支。
⑥ 合并成本 ≈ 你改的面积 × 别人改的面积,随分歧时间超线性上涨;小批量的作用是把这条曲线摁回近线性。
⑦ 测试自动化:谁写比写没写更关键——开发者创建并维护验收测试与高效能相关;主要由 QA 或外包创建维护的,与效能不相关。前提是测试可靠(绿就敢发、红就是真缺陷)+ 测试数据按需可得。
⑧ 收获不止速度:CD 同时预测更低的部署痛苦与倦怠、更强的组织认同、更生成型的文化,而文化又回过头撑住实践——形成良性循环。
⑨ 实操排序:先把测试修可靠,其余实践都站在这块地基上;地基不稳就强推每日合并,只会让主干长期红着、团队退回长命分支。
⑩ 读它的分寸:结论来自自愿问卷 + 推断性预测分析,方向性强但不是随机对照实验;「不相关」也不等于「有害」。