用 `small-change` 加速代码审查
Imprint 工程师平均合并的 PR 数量是两年前的 4 倍。不错。
但平均值背后还藏着更有意思的事:有两个团队的 PR 合并量在这段时间里翻了 10 倍。有一位工程师每周合并的 PR 数量是两年前普通工程师的 25 倍,还有好几个人正在逼近这个数字。这挺厉害的,而且从趋势线来看,一年后我们的平均水平会大幅超过今天的 p50(中位数),更接近今天的 p90。
更重要的是,我们不只是交付得更多,质量也提升了:事故数环比下降了 42%,严重事故数环比下降了 78%。我们一直都知道,质量与速度之间的取舍本来就不是一个特别有用的框架,但今天这一点已经无可辩驳。
沿着这条路走下去,我们和其他同样在这条路上前进的人一样,遇到了 PR 代码审查的问题。两年前,p50 的 PR 审查大约需要 33 分钟完成,现在要花大约 77 分钟。这条曲线的走势与 PR 合并数量高度相关,相关性强到解决这个问题成了我本周的重点工作之一。
我们解决了!开个玩笑,我们完全没解决,但我觉得我们目前的做法挺有意思,我们称之为 small-change。
本文讨论的工作由 Imprint 的许多人共同参与和完成,包括 Dan、Joy、Daniel、Lenny、Taylor、Ted 和 Annie 等等。
为什么要审查 PR?
我们审查 PR 有四个原因:
-
作者和审查者之间的知识分享——软件工程通常是通过师徒制学来的,代码审查是经验丰富的工程师教别人什么是好软件的主要方式。我们认为,当前的数量意味着这种知识分享将不得不转向对 PR 集群进行操作,而不是单个 PR。
-
防止错误——审查一直是捕获错误的高成本时机,我们认为有效的 CI/CD 以及像 poteto 的 pstack 这样的 harness 验证技术,是比审查更有效的防错机制。
-
防止恶意行为——我的经验是,即使是很仔细的代码审查,通常也会漏掉那些“有水平的恶意行为”,不过好在大多数恶意行为其实都很拙劣。我们认为,这两类行为最好通过组合手段来识别:固定规则(改动某些特定对象/类/文件必须走审查)、我们在基于 LLM 的会员支持体验中打磨出来的反滥用机制、审计,以及审计日志检查。
-
有记录的管控措施所承担的合规义务——这些措施可以改,但目前它们要求由独立的人工来审查我们一部分代码仓库的变更。
在现代开发范式下,我们认为这两个问题都有更好的解法。但我们也不想改得太急。
用 small-change 小步推进
我们相信,快速前进的方式是找到范围窄、可控的方式来验证新做法。为了通过不断迭代得到有效方案,我们提出了 small-change 的概念。它是这样运作的:
-
当一个拉取请求(PR)被标记为就绪,CICD 会判断它是否符合
small-change的条件。判断结果体现为一个通过的 GitHub 检查。同时还有一个标签用于可见性,但真正决定是否符合条件的是这个检查本身——它由构建流程管理,人工无法修改。(标签只用于初步筛选,检查仍会被独立验证。) -
满足以下所有条件的改动才算作
small-change:代码行数少于 1,000 行;我们的自动化审查机器人ai-code-review没有给出 p1 或 p2 级别的问题;作者在该服务或应用上有“经验”,定义为此前有 10 个以上合并到该服务或应用目录的 pull request。对于跨多个服务或应用的改动,作者必须在所有相关服务或应用上都有经验才符合条件;影响的服务或应用数量少于 N 个。前端 monorepo 中 N 为 1,后端 monorepo 中 N 为 3,因为后端典型改动通常同时涉及 gRPC 服务和公共 HTTP 网关;共享库和工具文件不适用small-change。每个仓库都有一个.small_change文件,允许按路径定制规则,方便我们持续调整行为。例如,涉及资金流动的服务可以被排除在外。 -
我们的 Slack 自动化会给每个 pull request 引用打上 reacji 标签,标明该 PR 的状态,比如测试失败、已批准但测试仍在运行、或者可以合并。我们新增了一个
small-changereacji,用来标识哪些 PR 符合small-change标准。 -
在内部技能仓库中,我们创建了两个技能,已分发到各个 harness:
review-small-change接收一组仓库列表,审查所有开放的、非草稿的 small-change,如果符合审查标准(所有检查通过,包括small-change检查,且不涉及支付和安全等敏感话题),则直接批准。重要的是,这个技能只有两个选项:批准或忽略。它从不评论 PR,以免“人工代理审查”泛滥——这种做法在一些团队中已经成了假借解决方案之名的瓶颈。review-pr-cluster则批量审查 pull request,找出其中的共同主题,建议讨论机会并补充验证。 -
我们设定一个团队共识:任何由
small-change引发的错误都是系统的失败,必须在系统层面解决——改进 ai-code-review、改进验证机制、改进 CICD、改进执行框架等。 -
代码行数少于 1,000 行。
-
我们的 ai-code-review 自动审查机器人没有给出 p1 或 p2 级别的问题。
-
作者对该服务或应用有“经验”,定义为:此前已有 10 个以上合并的 PR 进入该服务或应用的目录。如果改动跨多个服务或应用,作者必须在所有相关服务或应用中都有经验,才算符合条件。
-
影响的服务或应用数量少于 N 个。前端 monorepo 中 N 为 1,后端 monorepo 中 N 为 3(后端典型改动通常同时涉及一个 gRPC 服务和一个公共 HTTP 网关)。
-
共享库和工具文件不适用
small-change。 -
每个仓库有一个
.small_change文件,支持按路径定制规则,方便我们持续调优。例如,涉及资金流动的服务可以被排除在外。 -
review-small-change:接收一组仓库列表,审查所有开放的、非草稿的 small-change,如果满足审查标准(所有检查通过,包括small-change检查,且不涉及支付、安全等敏感话题),则直接批准。重要的是,这个技能只有两个选项:批准或忽略。它从不在 PR 上评论,避免“真人代理审查”泛滥——这种做法在一些团队里已经成为伪装成解决方案的瓶颈。 -
review-pr-cluster:批量审查 PR,识别反复出现的共性问题,并建议讨论和补充验证的机会。
实现和推广大约花了两天的零散时间,不过可以预见,这些参数我们会调很久。也许永远在调。
真人代理审查
我在上面 4.1 节提到过,但“真人代理审查”已经成为许多团队的一个有趣瓶颈。它之所以特别棘手,是因为它最初看起来像解决方案,但实际上让事情变得更糟。这个模式大致是:
-
团队被评审压得喘不过气
-
团队决定用本地测试工具来评审拉取请求
-
拉取请求收到大量评论,有些说得有道理,有些则不然。不仔细研究就分不清哪些是哪些,你也不知道哪些评论真正反映了评审者的观点。结果就是,你得花大量精力去反驳那些评审者自己可能都不同意的评论。
-
然后这些团队开始用测试工具去回应测试工具生成的评论,整个评审流程变成了一场幻觉,既不能促进学习,最重要的是,整个过程完全可以不需要其他团队成员参与。
凡是采用「人工代理评审」的情况,团队只要把精力投入到集中式评审机制、用测试工具循环处理集中评审的反馈,然后直接盖章通过,效果都会更好。
fleet:集中编排的测试工具
我简单提一下我们另一种减少代码评审量的方案,核心是集中编排的测试工具 fleet。(它类似于 Stripe 的 Minions,只是没有特别遵循一次性执行的思路。)我们依靠 fleet 在云端高度受控的测试环境中实现和验证软件,并用独立的评估机制来确定针对某项变更需要多少名独立评审者。对于评估为安全的变更,这个数字可以低至一个(比如 fleet 编写,一个人评审)。
结果 / 下一步 / 反馈
说实话,现在还太早,给不出有用的结果。从早期数据看,大约 10% 的变更符合 small-change 的标准。这些变更现在可以走快速审批通道,而且通常都能通过,除非触发了某个标记,一般是因为涉及安全或金钱相关的主题。
10% 虽然只是个小比例,但核心思路是成立的。最终成败取决于我们能否在未来几个月扩大这个比例,同时让验证机制越来越全面。说到底,这取决于我们改进验证的能力。在规模复杂度低、领域复杂度高的软件里做验证,比在高规模复杂度、低领域复杂度的产品里更难。后者用增量发布之类的手段效果特别好。别误会,这些手段仍然有效,只是当大多数用户配置和行为各不相同的时候,覆盖面会小一些。
大家对此反应并不一致。这和我们已经习惯的优秀工程实践差别很大,而且重新审视一个长期奉为最佳实践的做法是否已沦为教条,本身就让人不舒服。当前周期最让人振奋的地方是,我们每周都能重新审视这些从小习得的做法;最痛苦的地方是,一旦停止审视,我们很可能就会落后。
大家好,我是 Will Larson。
如果你想联系我,这里有一些我能帮上忙的方式。
书籍
我写了《An Elegant Puzzle》《Staff Engineer》《The Engineering Executive's Primer》和《Crafting Engineering Strategy》。




新闻通讯
如果你想获取更新,可以订阅每周邮件,或关注我的 RSS 源。
热门
-
构建内部智能体
-
“优秀工程管理”是一阵风
-
从重协调型转向重领导型的管理角色
-
工程组织资历结构模型
-
如何打造软件质量
近期
-
用
small-change加速代码审查 -
尝试软件工厂模式
-
路线图决策,而不是日期
-
中层管理岗位也是陷阱
-
被生成的需求与被压制的需求
相关