DEF (阿里巴巴前端研发平台)在 FY21 基于 Aone (阿里巴巴代码托管平台)能力和 KAITIAN 纯前端版本搭建了一套 CodeReview 系统,致力于面向前端提供更好的 CodeReview 体验,建立起更符合前端特点的质量评价体系。《CR 质量思考》系列文章共分为三个部分:
本篇主要介绍目前已上线的分阶段评审的设计思路与实现,并结合相关的使用数据分析目前设计存在的问题,并尝试给出优化版本的方案。
上两篇文章提到,大尺寸 CR 对 CR 的质量会有非常明显的影响,但是由于业务复杂度的必然性,部分变更尺寸必然会达到那个代码规模,无法通过变更拆分的方式来解决,在 DEF 的 CR 体系中,有接近 20% 的 CR 达到了这个规模。在这一背景下,如何对单一变更进行 CR 的拆分成为了一个亟待解决的问题。上一篇文章中我们提到了几种解法:
阶段化代码评审
本文会详细的介绍目前已经上线的阶段化代码评审的设计与实现,并基于现有阶段化评审的数据进行探讨,提出新版阶段化评审的解决方案。
目前的常规评审流程如下图所示:在常规评审中,一次变更代码量有多大,评审时所看到的代码量就有多大。而阶段化评审的核心思想就是,将单次代码评审拆成多个评审进行 CR,每次 CR 只面向开发者提交的一个阶段代码进行,不引入额外的变更信息。阶段化评审的理想化推导如下图所示:按照上图的流程,对于开发者来说,只需要在写完一个阶段的代码后,提交一次评审,并结合评审人的反馈信息完善当前阶段的代码,完成后再开始下一阶段的开发和评审即可。对于评审人来说,只需要关注单次收到的 CR 评审,流程对他基本上是无感的。
要实现在每个阶段评审内 只需要关注本次 CR 新增内容 的效果,基于版本拆分 CR 的能力是基础。版本最小的粒度定义为每个 Git Push 的操作,每次 Push 可能包含 0 个(比如 git reset 场景)或多个 commit,会使得远程库的分支处于某个特定的 commit 状态。我们要实现的就是支持 Push 版本之间的对比。一般情况下我们直接使用版本对应的 commit 进行 Diff 即可,但是在 mergeBase 发生变化的场景下,我们需要一套兼容算法来抹掉 mergeBase 变化带来的变更,该算法的简单推导如下:完整的推导过程见文章:《纯前端 IDE CR:面向版本的 CR 系统实现》
一次评审的状态流转过程为:对应的界面交互为:评审人在查看评审时,会看到基于他上次评审通过/不通过的版本基础上的新变更,同时点击每个版本节点上的变更信息(文件数或代码行数)时,会跳转到对应小版本的diff信息,相关的阅读时长、已读、未读文件数据均会关联到对应的小版本 CR 数据内。对于用户而言,每个 CR 的小版本基本等效于一个子 CR 单,但是可以关联上次评审的评论互动信息。
为了让整个 CR 流程可以按照阶段化的方式运行起来,同时保证代码的尺寸大小符合预期,DEF 提供了一套完整的代码量检测 & 通知机制,在用户推送代码时通过 webhook 进行触发(在研发平台内通过轮询检测),基于 CR 单当前所处的状态及变更代码量,通知对应的开发者 or 评审人执行下一步操作,通知的方式有钉钉通知和页面提醒两种。目前的通知场景如下:
现有的 CR 阶段化能力于 2021.06.24 正式上线,上线之后截止到 2021.07.14,在总共有 1500+ 个 CR 使用过阶段化的能力(至少拆分为两个阶段),同期的 CR 单总量为 20000+ 个 。从 2021.07.15 的界面埋点数据来看,查看 CR、提交 CR 和展开分阶段评审详情的按钮的点击 PV 分别约为 3000 次,1500 次和 800 次。
看上去使用数据还可以,但从单次变更行数的信息来看,绝大多数的阶段化 CR 单只是在评审的反馈与修改的循环流程内简单使用了阶段化的能力(数据上体现为后续阶段仅修改了几行代码),并没有按照我们的预期将一个大 CR 拆分成若干小规模的 CR。经过我们的复盘和用户调研,我们发现之前设计的 CR 阶段化流程存在一个实际开发过程中非常难以落地的环节:如上图所示,之前为了让评审人无感,我们的版本生成过程其实依赖了两部分:一部分是开发者的提交环节,另一部分是评审人和开发者的反馈环节。只有在评审人觉得当前版本没有问题的时候,才会评审通过 生成一个版本。由于评审本身是一个异步流程,同时依赖开发者和评审人导致了这个阶段化的流程难以在实际评审中落地,往往是评审人进来评审的时候,评审的内容已经随着开发者后续的代码提交进入了下一阶段,而不是开发者预期的那个版本。这一设计使得阶段评审的实用性大打折扣。
解决这个问题的关键点在于,把版本生成流程的评审人操作依赖去掉,让开发者成为划分评审阶段的唯一条件。考虑到提交新的阶段评审这一环节和常规流程最终的评论反馈循环一样,都是在提交新的代码解决之前代码存在的问题,我们把阶段评审的评论反馈循环的环节拿掉,使用提交新阶段评审的环节来替换。也就是说,把流程变成这样:如果评审人收到的是阶段化评审,那么他会看到的只有当前阶段内的评审内容;如果收到的是最终评审,那么开发者在评审提交后后续提交的修改代码,都会完整的展现在评审信息中,与常规评审无异。最终评审时可以切换到之前的评审阶段作为参考,同时之前评审的评论信息也都会展现在评审中。
分阶段代码评审理论上可以很好的支持大变更场景的代码评审需求,通过让开发者主动将变更的代码拆分为几个阶段,一方面可以让评审人不用面对完整复杂的代码变更,可以参考阶段的描述信息,关注小规模的代码变更;另一方面,评审人可以提前处理分阶段的评审,有效增加评审的时长。
分阶段代码评审是 DEF 在 CR 质量方向上的一个重要的探索,目前我们也在不断的补齐能力和优化体验,让代码量大的前端变更可以有更好的方式来做 CR,做到在不影响业务研发效率的同时,为安全生产保驾护航。
往期推荐
Code Review 质量思考:解法