现代代码审查:Google案例研究
摘要
使用基于工具的轻量级代码检查代码更改(又名现代代码审查)已成为广泛的规范,应用于各种开源和产业系统。在本文中,我们对Google的现代代码审查进行了探索性研究。Google很早就引入了代码审查并经过多年的发展;我们的研究揭示了为什么Google引入了这种做法并分析了当前的状态,经过数十年的代码变更和数百万条代码审核。通过12次访谈,对44位受访者的调查以及分析的900万条已审核变更的审核日志,我们调查了Google进行代码审查的动机,当前做法,以及开发人员的满意度和挑战。
1.引言
对等代码审查,是除了作者以外的开发者们对源代码进行手动检查,被认为是对提高软件项目质量的一种有价值的工具。在 1976年,Fagan正式制定了高度结构化的代码审查流程——代码检查。多年来,研究人员提供了有关代码检查的优势的证据,特别是在发现缺陷上,但麻烦的是费时,这种方法的同步性特点阻碍了它在实践中的推广。现今,大多数组织都采用更轻量级的代码审查实践来限制检查效率低下。现代代码审查是(1)非正式(与Fagan风格相反),(2)基于工具的,(3)异步,(4)聚焦于审查代码更改。
一个开放的研究挑战是:在这种新颖的背景下,了解哪些实践代表了宝贵而有效的审查方法。Rigby和Bird定量分析了来自跨领域软件项目以及组织的代码审查数据,发现五个高度趋同的方面,他们猜想其他的项目也有这个规律性。Rigby和Bird的分析基于有价值的广泛的观点(分析了多个来自不同的环境的项目)。对于由Basili倡导的知识实证体系的发展,同样重要的是要考虑对单个案例进行分析的集中和纵向的观点。本文扩展了Rigby和Bird的工作,着重于审查实践和特色,主要是:在Google成立,一家公司拥有数十年的代码审查的历史和大量的每日审查借鉴。本文可以(1)对从业人员规定进行代码审查和(2)吸引研究人员想了解和支持这一新颖过程的人。
从Google非常早期的历史开始,代码审查就已经成为软件开发中必不可少的一部分;因为它很早就引入了,已经成为了Google文化的一个核心部分。在Google,代码审查的过程和工具经过反复完善了十多年,应用在每天全球数十个办公室中,超过25,000名开发人员的超过20,000行源代码的更改。
我们以探索性调查形式进行分析聚焦于代码审查的三个方面,并扩展了Rigby和Bird的成果:(1)驱动代码审查的动机,(2)当前实践,以及(3)开发人员对代码审查的感受,专注于特定审查遇到的挑战(审核过程中的中断)和满意度。我们的研究方法结合了来自多个数据源的输入:对Google开发人员进行12次半结构化的访谈;一个内部调查,发送给了最近做个变更审查的工程师,并收到44条回复;一组来自两年间的Google代码审查工具产生的900万条评论的数据。
我们发现:相比其他情况,Google的流程明显更轻松,基于一位审阅者,快速迭代,小更改,以及集成紧密代码审查工具。由于围绕代码审查发生的交互是复杂的,中断审查仍然存在。不过,开发人员认为此过程很有价值,确信当规模很大的时候,可以很好地发挥作用,并且,进行这个过程有若干原因,也取决于作者与审查者之间的关系。最后,我们发现关于使用代码审查工具,不仅可以协作审查,而且还有个一个很重要的发现:代码审查可以作为一种教学工具。
2.背景和相关工作
我们描述了文献研究中的审查过程,然后我们详细介绍这些融合代码审查的做法流程。
2.1 代码审查过程和情景
代码检查。软件检查是第一个正式的代码审查流程。这个高度结构化的过程涉及计划,概述,准备,检查会议,返工和跟进。代码检查的目标是在同步检查会议中发现缺陷,作者和审稿人坐在同一会议室内来检查代码更改。Kollanus和Koskinen汇编了有关代码检查的最新文献调查研究。他们发现绝大多数关于代码检查的研究本质上是经验性的。代码检查作为一种发现缺陷的技术的整体价值和促使检查者读代码的价值存在共识。总体而言,与Internet的普及和异步代码审查流程的增长,自2005年以来,代码检查的研究有所下降。
通过电子邮件进行异步审查。直到2000年代后期,大多数大型OSS项目都采用一种远程异步审查的形式,这依赖于补丁发送的通讯渠道,如邮件列表和问题跟踪系统。在这种情况下,项目成员评估贡献的补丁程序并通过这些渠道请求修改。当补丁被认为质量足够高时,核心开发人员会将其提交给代码库。受信任的提交者可能具有提交到审查过程,而不是进行提交前的审查。Rigby等人,是最早在这种环境下进行广泛工作的人之一;他们发现,这种类型的审查“与[代码检查]几乎没有共同点,只是相信同行会有效地发现软件缺陷” 。Kononenko等人,分析了这种情况,并且发现审查响应时间和接受程度和社会因素相关,例如,审查者的工作量和改变作者的经验,这些是代码检查所无法反映的。
基于工具的审查。为了使修补程序审查的过程结构更加合理,OSS和工业设置中出现了几种工具。这些工具支持审阅过程的持久工作:(1)补丁的作者将其提交给代码审阅工具,(2)审阅者可以看到建议代码与更改的差异,(3)可以与作者和其他审稿人就特定的话题展开讨论,然后(4)作者可以提出修改意见,以解决评审者的意见。此反馈周期将持续到每个人都满意或补丁被丢弃为止。不同的项目使用了他们的工具来支持他们的过程。Microsoft使用CodeFlow,该工具跟踪每个人(作者或审阅者)的状态以及他们在进程中的位置(签名,等待,审阅);CodeFlow不会阻止作者未经批准而提交更改,并支持在评审线程中聊天。Google的Chromium项目(以及其他几个OSS项目)依赖于外部可用的Gerrit;在Chromium中,只有经过审阅者的明确批准并自动确认更改不会破坏构建,更改才会合并到master分支中。在Gerrit中,未分配审查者也可以发表评论。VMware开发了开源的ReviewBoard,它将静态分析集成到审查过程中。这种集成依赖于变更作者手动请求分析,并且已经证明可以提高代码审查的质量。Facebook的代码审查系统Phabricator,使审查者可以“接管”更改并自行提交,并提供了挂钩以进行自动静态分析或持续的构建/测试集成。
在基于工具审查的背景下,研究人员调查了代码更改接受或响应时间与更改后的代码和作者的特征之间的关系,以及审阅者之间的协议。根据工业和OSS开发人员的意见,还进行了定义什么构成良好的代码审查。
基于分叉模式的开发模型。在GitHub上,拉请求的过程中,开发人员想要对现有的git仓库进行更改,就要对其fork进行更改。在发出拉请求后,会出现在拉请求的列表中展示项目中的问题,任何可以看到该项目的人都可以看到。Gousios等人对拉请求集成者和贡献者的实践和碰到的问题进行了定性研究,发现与基于工具的代码审查有类似的方法。
2.2 代码审查中的融合实践
Rigby和Bird提出了第一项也是最重要的工作,这些工作试图跨几个代码审查过程和上下文确定融合的实践。他们考虑了使用基于电子邮件审查的OSS项目,使用Gerrit的OSS项目,使用基本代码审查工具的AMD项目以及使用CodeFlow的Microsoft。他们分析了这些项目的过程和数据,以描述多个角度,例如迭代开发,审查者选择和审查讨论。他们确定了所有已考虑项目都融合到的五种现代代码审查实践(表1)。我们将使用其ID(例如CP1)来引用这些做法。基本上,他们在快速,轻量级过程(CP1,CP2,CP3)方面达成了一致,很少有人参与(CP4)进行小组问题解决(CP5)。
3.方法论
本节描述了我们研究的问题和背景;它还概述了我们的研究方法及其局限性。
3.1 研究的问题
这项研究的总体目标是调查Google的现代代码审查,这一过程涉及成千上万的开发人员,并且经过了十多年的改进。为此,我们进行了探索性调查,围绕三个主要研究问题进行了结构设计。
RQ1:Google进行代码审查的动机是什么?Rigby和Bird发现动机是现代代码审查的融合特征之一(CP5)。在此可以了解,动机和期望推动了Google的代码审查。特别是,我们既考虑了引入现代代码审查的历史原因(因为Google是最早使用现代代码审查的公司之一),也考虑了当前的期望。
RQ2:Google的代码审查实践是做什么?Rigby和Birdregard根据流程(CP1),速度和频率(CP2),分析变更的大小(CP3)和审阅者数量(CP4)来执行流程本身。我们对Google的这些方面进行了分析,以调查与以前的研究相比,对于具有更长代码审查历史,明确文化和大量审查记录的公司来说,同样的发现是否成立。
RQ3:Google开发人员如何看待代码审查?最后,在我们的最后一个研究问题中,我们有兴趣了解Google开发人员如何看待其公司中已实施的现代代码审查。为了更好的理解实践(因为感知驱动行动)和指导未来的研究,这个探索很必需。我们聚焦于两方面:一些特定的审查,比如:开发人员有中断审查的经历;在面临一些挑战时开发人员对审查是否满意。
3.2 研究的背景
我们简要描述了关于我们方法论的研究背景。有关Google代码审查过程和工具的详细说明,请参见第5.1节。
Google的大多数软件开发都在一个整体的源代码存储库中(mono-repo),通过内部版本控制系统访问。由于Google代码审查是必需的,因此,每次向Google源代码控制系统提交代码,都先要使用CRITIQUE进行代码审查,CRITIQUE是一个内部开发的,集中的,基于Web的代码检查工具。开发工作流程基于Google的整体代码库,包括代码审查过程,是非常统一的。就像第2节中描述的工具一样,CRITIQUE允许审查者看到提议更改代码和开始讨论前明确的代码行处。CRITIQUE提供了大量的登录功能;记录开发者使用该工具的交互(包括打开工具,查看差异,创建评论和接受更改)。
3.3 研究的方法
为了回答我们的研究问题,我们采用定性和定量相结合的方法,该方法结合了以下几种来源的数据:在与Google从事软件开发工作的员工进行的半结构化访谈,来自代码审查工具的日志以及对其他员工的调查。我们使用访谈作为一种工具来收集有关进行代码审查(RQ1)动机的多样性(与频率相对比)的数据,并激发开发人员对代码审查及其挑战(RQ3)的理解。我们使用CRITIQUE的日志来量化和描述当前的审查实践(RQ2)。最后,我们使用调查来确认访谈(RQ1)中出现的代码审查的多种动机,和激发开发人员对过程的满意度的因素。
会谈。我们与选定的Google员工进行了一系列面对面的半结构化访谈,每次访谈大约需要1个小时。最初的可能参加者是使用滚雪球采样法来选择的,首先是论文作者所知道的开发人员。从此库中,选择参与者以确保团队的分散,技术领域,工作角色,公司内部的时间长度以及在代码审核过程中的角色。访谈脚本包括有关代码审查的动机,最近审查/撰写的变更,以及最佳/最差审查经历的问题。在每次访谈之前,我们都会回顾参与者的审查历史,并找到要在访谈中会讨论的更改;我们选择这些更改,是根据互动次数,参与对话的人数,以及是否有很多令人惊讶审查点评。在访谈的观察部分中,要求参与者在审阅即将发生的变更时思考,并提供一些明确的信息,例如开始审阅的切入点。访谈一直持续到达到饱和,并且访谈提出了大致相似的概念。总体而言,我们对从Google工作1个月到10年(平均5年),软件工程和站点可靠性工程的员工进行了12次面试。他们包括技术主管,经理和个人贡献者。每次访谈涉及三到四个人:参与者和2-3个受访者(其中两个是本文的作者)。采访由一名采访者实时转录,而另一名采访者提出问题。
采访数据的开放编码。为了确定采访数据中出现的广泛主题,我们进行了一次开放编码。两位作者讨论了访谈笔录,以确立共同的主题,然后将其转换为编码方案。然后,另一位作者对讨论的注释进行了封闭编码,注释是对确认的主题。我们对其中不止一个采访进行了迭代,直到我们就该计划达成协议。我们还跟踪了上下文(审稿人与作者之间的关系)中提到的这些主题。问题设计和分析过程的结合意味着我们可以讨论结果中的稳定主题,但不能有意义地讨论发生的相对频率。
审查数据的分析。我们定量的分析数据,数据是代码审查过程中使用CRITIQUE产生的日志。我们主要关注Rigby和Bird发现的融合实践(CP)相关的指标。为了方便对比,我们不考虑没有审查者的更改,因为我们对有明确代码审查过程的更改感兴趣。我们将“审阅者”视为批准代码更改的任何用户,而不论更改作者是否明确要求他们进行审阅。我们使用基于名称的启发式的方法来自动化流程产生的更改。我们专门关注Google主要代码库中发生的更改。我们还排除了在研究时尚未落实的更改,以及我们的差异工具报告的源码零行变化量的更改,例如,仅修改二进制文件的更改。在Google,平均每个工作日,提交了约20,000个符合上述过滤条件的更改。我们的最终数据集包括2014年1月至2016年7月,由25,000多名作者和审阅者创建的符合这些标准的大约900万项更改,以及从2014年9月至2016年7月之间的所有更改中收集的大约1300万条审查评论。
调查。我们创建了一个在线调查表,并发送给了98位最近提交了代码更改的工程师。代码更改已经过审核,因此我们定制了调查表,以询问受访者如何看待代码审核,关于他们最近的特定更改;这种策略使我们可以减轻召回偏见,但仍可以收集全面的数据。该调查包括三个关于收到的评论的价值的Likertscale问题,一个关于评论对其更改影响的多项选择(基于访谈产生的期望)和一个可选的“其他”回答,以及一个开放式- 最终提出质疑,以引起受访者对所收到的评论,代码评论工具和/或整个过程的意见。我们收到了44份有效的调查问卷答复(45%的答复率,在软件工程研究中被认为很高了)。
3.4 有效性和局限性的威胁
我们描述了研究方法所带来的对有效性和工作成果局限性的威胁,以及为缓解这些挑战所采取的行动。
内部有效性——可信度。关于评论数据的定量分析,我们使用启发式方法从定量分析中滤除机器人撰写的更改,但这些启发式方法可能允许某些机器人撰写的更改;我们对此进行了缓解,因为我们仅包括具有人工审核者的由机器人撰写的更改。关于定性调查,我们使用了开放式编码来分析受访者的答案。该编码可能会受到编写该编码的作者的经验和动机的影响,尽管会通过让多个编码人员参与来减轻这种偏见。决定参加我们的访谈并自由选择调查的员工决定这样做,从而引入了自我选择偏见的风险。因此,对于不选择参与的开发人员而言,结果可能会有所不同;为减轻此问题,我们将访谈和调查中的信息相结合。此外,我们使用雪球抽样方法来确定要面试的工程师,这有抽样偏差的风险。尽管我们试图通过面试具有各种工作角色和职责的开发人员来减轻这种风险,但我们访谈的开发人员可能有其他因素在整个公司中并不适用。为了减轻主持人的接受偏见,参与定性数据收集的研究人员不属于CRITIQUE团队。社会可取性偏见可能已经影响了答案,使其更适合Google文化。但是,在Google鼓励人们批评和改进发现的工作流程,从而减少这种偏见。最后,我们没有采访与专家评审员(例如安全评审)进行交互的研究科学家或开发人员,因此我们的结果偏向于一般开发人员。
通用性——可移植性。我们的结果可能无法推广到其他情况,而是我们对多年实践和数百万次细化检查后,仍会发生的多种多样的做法和审查中断感兴趣。鉴于基本代码检查机制在多个公司和OSS项目中的相似性, 有理由认为,如果审查过程达到相同的成熟度并使用可比较的工具,则开发人员将具有类似的经验。
4.结果:动力
在我们的第一个研究问题中,我们首先要研究导致这一过程的原因,从而寻求理解开发人员在Google进行代码审查时的动机和期望。
4.1 一切如何开始
Google的代码审查最早是由第一批员工之一引入的;本文的第一作者采访了该员工(以下简称 E),以更好地理解代码审查及其演变的最初动机。E 解释了代码审查引入的主要推动力是:迫使开发人员编写其他开发人员可以理解的代码 ; 这被认为很重要,因为代码必须作为未来开发人员的老师。Google在代码审查中的引入标志着从研究代码库(已优化为快速原型开发)向生产代码库的过渡,在此基础上考虑未来工程师阅读源代码。代码审查也被认为能够确保不止一个人熟悉每一段代码,从而增加了知识在公司中的驻留机会。
E 重申了这样一个概念,即尽管审阅者发现错误是很棒的,但在Google引入codereview的首要原因是为了提高代码的可理解性和可维护性。但是,除了最初进行代码审查的教育动机外,E 解释说,开发人员的三个其他好处很快就在内部对开发人员变得显而易见:检查样式和设计的一致性;确保足够的测试;通过确保没有任何开发人员可以在没有监督的情况下提交任意代码来提高安全性。
4.2 目前的期望
通过对访谈数据进行编码,我们确定了Google开发人员期望从代码审查中获得的四个关键主题:教育,维护规范,把关和事故预防。教育从代码审查中学习或学习,并与引入代码审查的最初原因保持一致;规范是指组织对自由选择的偏好(例如格式或API使用模式); 网守涉及围绕源代码,设计选择或其他工件的边界的建立和维护;事故是指引入错误,缺陷或其他与质量相关的问题。
这些是审查过程中的主要主题,但是代码审查也用于追溯历史。开发人员在审查过程完成后对其进行评估;代码审查可以浏览历史记录 代码更改的内容,包括发生了什么注释以及更改如何演变。我们还注意到开发人员使用代码回顾历史来了解错误的引入方式。从本质上讲,代码审查使将来的变更审核成为可能。
在我们的调查中,我们进一步验证了这种编码方案。他们可以选择四个主题中的一个或多个主题和/或自己撰写。较早确定的四个主题中的每个主题都是在特定代码审查的背景下由8至11个受访者选择的,因此,可以更加确信上述编码方案与开发人员对代码审查价值的理解相一致。
尽管这些期望可以覆盖以前在Microsoft [4]上获得的期望,但正如我们的参与者所解释的那样,Google的主要重点是教育以及代码的可读性和可理解性,这与历史动因相吻合。因此,关注点与Rigby和Bird的关注点不一致(即,小组解决问题的活动)[33]。
发现1. Google进行代码审查的期望并不以解决问题为中心。Google引入审核,目的是确保代码的可读性和可维护性。当今的开发人员除了维护规范,跟踪历史记录,保护措施和预防事故外,还从教育角度进行了了解。发现缺陷受到欢迎,但不是唯一的重点。
如前所述,在对访谈笔录进行编码时,我们还跟踪了提到主题的评论上下文,我们发现这些不同主题的相对重要性取决于作者与评论者之间的关系(图1)。例如,维护工程师与具有不同资历的工程师(项目负责人,专家可读性审阅者或“新”团队成员)之间的规范冲突,而与同伴或其他团队相比则少一些,而看门人和事故预防则是主要的。具有广泛的价值,并包含多种不同的关系。
图1. 关系图,描述了哪些评论期望主题主要出现在特定作者/评论者上下文中。
发现2.对Google进行特定代码审查的期望取决于作者与审查者之间的工作关系。
5.结果:实践
在我们的第二个研究问题中,我们描述了代码重审过程,并将其定量方面的内容与先前工作中发现的趋同做法进行了比较[33]。
5.1 描述审查过程
Google的代码审查与两个概念相关:所有权和可读性。我们首先介绍它们,然后描述审阅过程的流程,然后得出内部审阅工具CRITIQUE与其他审阅工具不同的特点。
所有权。Google代码库以树结构排列,其中每个目录都由一组人员明确拥有。尽管任何开发人员都可以提议对代码库的任何部分进行更改,但是相关目录(或父目录)的所有者必须在提交更改之前对其进行审核和批准;甚至目录所有者也要在提交之前检查其代码。
可读性。Google定义了一个称为可读能力的概念,该概念很早就引入了,以确保代码库中的代码风格和规范保持一致。开发人员可以使用特定语言获得可读性认证。为了应用可读性,开发人员将更改发送给一组有可读能力的审阅者。一旦这些审阅者确信开发人员了解某种语言的代码风格和最佳实践,便会为开发人员授予该语言的可读性。每次更改都必须由具有所使用语言可读性证明的人员编写或审阅。
代码审查流程。审查流程与评论紧密结合,其工作方式如下:
1。创建:作者开始修改,添加或删除某些代码;一旦准备好,他们就会进行更改。
2。预览:作者然后使用CRITIQUE来查看更改的差异,并查看自动代码分析器的结果(例如,来自Tricorder [36])。准备就绪后,作者将更改发送给一个或多个审阅者。
3。评论:审阅者可以在Web UI中查看差异,并随时起草评论。程序分析结果(如果存在)也对审阅者可见。未解决的评论显示为变更作者必须解决的操作项目。已解决的评论包括可选或信息性评论,可能不需要变更作者采取任何行动。
4。解决反馈:作者现在可以通过更新更改或通过回复评论来处理注释。更新更改后,作者将上载新快照。作者和审阅者可以查看任意一对快照之间的差异,以了解发生了什么变化。
5。批准:解决所有评论后,评论者会批准该更改并将其标记为“ LGTM”(对我来说很好 Looks Good To Me)。要最终进行更改,开发人员通常必须至少获得一名审阅者的批准。通常,只需一名审阅者即可满足上述所有权和可读性要求。
我们尝试量化“轻量级”审阅的方式(CP1)。我们通过检查变更作者邮寄了一组可解决以前未解决的注释的评论来衡量评论中来回的次数。我们假设一个迭代对应于一个作者解决某个评论的一个实例;零重复意味着作者可以立即提交。我们发现所有更改中有80%以上最多涉及解决评论的重复。
建议审阅者。要确定最佳的人来重新审阅更改,CRITIQUE依靠一种工具来分析变更并建议可能的审阅者。此工具确定满足更改中所有文件的审阅要求所需的最小审阅者集。请注意,通常只需要一名审阅者,因为更改通常是由拥有文件查询所有权和/或可读权的人创作的。该工具对最近编辑和/或审阅所包含文件的审阅者进行优先级排序。由于尚未建立新的团队成员,因为他们尚未建立审核/编辑历史记录,因此已明确添加为他们。未分配的审阅者还可以对更改发表评论(并可能批准)。寻找审阅者的工具支持通常仅在文件更改超出特定团队的情况下才需要。在一个团队内,开发人员知道向谁发送更改。为了将可能发送给团队中任何人的更改,许多团队使用一种系统,该系统将循环发送到团队电子邮件地址的审阅分配给配置的团队成员,同时考虑到审阅负载和休假。
代码分析结果。CRITIQUE将代码分析结果显示为注释以及人工注释(尽管颜色不同)。分析人员(或审阅者)可以提供建议的编辑,这些编辑可以被提议,也可以通过评论应用于变更。为了在更改提交之前审核更改,Google的开发还包括预提交挂钩:检查失败需要开发人员显式覆盖以启用提交的地方。提交前检查包括基本的自动样式检查和运行与变更相关的自动测试套件。所有预提交检查的结果在代码查看工具中可见。通常,会自动触发预提交检查。这些检查是可配置的,以便团队可以强制实施特定于项目的不变量,并自动将电子邮件列表添加到更改中,以提高意识和透明度。除了预先提交结果外,CRITIQUE还可以通过Tricorder [36]显示各种自动代码分析的结果,这些分析可能不会阻止提交更改。分析结果包括简单的样式检查,更复杂的基于编译器的分析通过以及特定于项目的检查。目前,Tricorder包括110个分析仪,其中5个是用于数百次附加检查的插件系统,总共可分析30多种语言。
发现3. Google代码审核过程与轻量级和灵活的融合做法保持一致。但是,与其他研究过的系统相比,所有权和可读权是明确的,并且起着关键作用。审阅工具包括审阅者推荐和代码分析结果。
5.2 量化审核流程
我们复制了Rigby和Bird发现的CP2-4的定量分析,以便将这些实践与Google融合的特征进行比较。
审查频率和速度。Rigby和Bird发现快节奏的迭代开发也适用于现代代码审查:在他们的项目中,开发人员的工作间隔非常短。为了找到答案,他们分析了评论的频率和速度。
在Google,就频率而言,我们发现处于中位数上的开发者每周大约进行3次更改,而80%的开发者每周进行少于7次更改。同样,开发人员每周审核的变更中位数为4,而80%的审阅者每周审核的变更少于10。在速度方面,我们发现开发人员必须等待对其更改的初步反馈,对于较小的更改,平均时间少于一小时,对于较大的更改,平均时间少于5小时。整个审阅过程的总体(所有代码大小)中值延迟小于4小时。这比Rigby和Bird [33]报告的平均批准时间要低得多,AMD的批准时间中位数为17.5小时,Chrome OS为15.7小时,三个Microsoft项目为14.7、19.8和18.9小时。另一项研究发现,微软批准的平均时间为24小时[14]。
审查规模。Rigby和Bird认为,只有通过较小的变更来审查并随后分析审查规模,才能实现快速审查时间。在Google,正在考虑的更改中,超过35%仅修改一个文件,而大约90%的修改少于10个文件。超过10%的更改仅修改一行代码,而修改的行数的中位数为24。更改位数的中位数显着低于Rigby和Bird对AMD(44行),Lucent(263行)和Bing等公司的报告。,Microsoft的Office和SQLServer(在这些界限之间的某个位置),但符合开放源代码项目中的更改大小[33]。
审查者和评论的数量。甚至在经过深入研究的代码检查中,研究人员的最佳人数一直存在争议[37]。Rigby和Bird调查了所考虑的项目是否收敛到了类似数量的参与评审人员。他们发现这个数字是两个,无论是否明确邀请了审阅者(例如,在Microsoft项目中,邀请的中位数最多为4个审阅者),或者是否公开广播了更改以进行审阅[33]。
相比之下,在Google中,只有不到25%的更改拥有多于一名审阅者,而超过99%的更改最多具有五名审阅者,中位审阅者人数为1。较大的更改通常平均会拥有更多的审阅者。但是,即使平均变化非常大,平均也需要不到两名审稿人。
Rigby和Bird还发现“当活跃于[超过2]位审稿人时,有关更改的评论数量最少” [33],并得出结论,两名审稿人发现缺陷的最佳数量。在Google,情况有所不同:审阅人数越多,对更改的评论平均数就越多。此外,每次更改的平均注释数随行数的变化而增加,对于大约1250行的更改,每个更改的最高注释数为12.5。大于此的更改通常包含自动生成的代码或较大的删除,从而导致平均注释数较低。
发现4.与先前调查的其他项目相比,Google的代码审查已将审查过程融合到一个过程中,该过程的审查速度显着加快且变更幅度较小。此外,与其他项目中的两名审阅者相比,一名审阅者通常被认为足够。
6.结果:开发人员的看法
我们最后一个研究问题是通过Google的代码审查来调查开发人员的挑战和满足感。
6.1 Google的代码审查中断
以前的研究调查了整个审查过程中的挑战[4,26],并提供了令人信服的证据,这也被我们作为工程师的经验所证实,理解要审查的代码是一个主要障碍。为了拓宽我们的经验知识体系,我们在这里集中讨论特定审查(“审查中断”)中遇到的挑战,例如延误或分歧。
对我们的访谈数据的分析提出了五个主要主题。前四个主题认为审查中断在过程中的相关因素有:
距离:受访者从两个角度感知代码审阅的距离:地理(即作者与审阅者之间的物理距离)和组织(例如不同团队或不同角色之间的物理距离)。这两种类型的距离都被认为是导致审阅过程延迟或导致误解的原因。
社会互动:受访者认为代码审阅中的交流有可能从两个方面导致问题:措辞和权力。措辞是指有时作者对评论发表敏感的事实。对评论的情感分析提供了证据,表明带有负面语气的评论不太可能有用[11]。权利是指使用代码审查过程来诱使他人改变自己的行为;例如,拖延审核或保留批准。措辞或权利在审查中,可能会使开发人员对检查过程感到不舒服或沮丧。
审查主题:访谈提到了关于代码审查是否是重新审查某些方面的最合适上下文(尤其是设计审查)的分歧。这导致期望值不匹配(例如,某些团队希望大多数设计在第一次审阅之前完成,其他团队希望在审阅中讨论设计),这可能导致参与者之间以及过程中产生摩擦。
背景:受访者让我们看到,由于不知道是什么导致了这种变化,所以会产生误解;例如,如果变更的理由是解决生产问题的紧急解决方案或“有个不错的改进”。预期结果的不匹配会导致延迟或沮丧。
最后一个主题是工具本身:
定制化:一些团队对代码审查有不同的要求,例如,关于需要多少审查者。这是技术上的审查中断,因为批评中并不总是支持任意定制,并且可能引起对这些政策的误解。根据反馈,CRITIQUE最近发布了一项新功能,该功能允许更改作者要求所有审阅者签名。
6.2 满意度和时间投入
为了了解已确定问题的重要性,我们使用了调查的一部分来调查代码审查是否总体上被认为是有价值的。
我们发现(表2)在Google内部代码审查被普遍认为是有价值和有效的–所有受访者都同意代码审查很有价值的说法。我们对CRITIQUE进行的内部满意度调查反映了这种观点:97%的开发人员对此感到满意。
在特定变化的背景下,情绪变化更大。最不满意的答复与很小的更改(1个字或2行)或与实现某些其他目标所需的更改(例如,从源代码的更改触发过程)相关。但是,大多数受访者认为,他们所做的更改的反馈量是适当的。在这3个中,有8位受访者认为注释无济于事,并指出,所审查的更改是小的配置更改,对代码审核没有影响。只有2位受访者表示评论中有bug。
表2. 用户满意度调查结果
为了根据满意度对答案进行情境化,我们还调查了开发人员花费在审阅代码上的时间。为了准确量化审阅者所花费的时间,我们跟踪了开发人员与CRITIQUE的互动(例如,打开选项卡,查看了差异,评论,批准了更改),以及其他工具来估算开发人员每周花费多长时间来审核代码。我们将开发人员交互的顺序分组为一定的时间段,将“审阅会话”视为与变更提交者以外的其他开发人员进行的,与同一未提交变更相关的交互顺序,每次相隔不超过10分钟。从2016年10月开始的五周内,所有审核会话所花的总小时数,然后计算每周每位用户的平均值,过滤出我们在过去五周内都没有数据的用户。我们发现开发人员平均花费3.2(平均每周2.6个小时)来审查更改。与OSS项目的6.4小时/周的自我报告时间相比,这个数字很低[10]。
发现5.尽管经过了多年的改进,但Google的代码审查仍面对审查中断。这些主要与评论周围发生的互动的复杂性有关。但是,开发人员强烈认为代码审查是一个有价值的过程,开发人员每周花费大约3个小时进行审查。
7.讨论
我们讨论了这项调查中出现的主题,这些主题可以启发从业人员建立代码审查流程,并激发研究人员在未来的调查中。
7.1 真正轻量级的过程
现代代码审查的诞生是它减轻了繁琐的代码检查的负担[4];实际上,Rigby和Bird在他们对整个系统的调查中都证实了这一特征(CP1)。在Google,代码审查已汇聚到一个更加轻量级的过程,开发人员发现该过程既有价值又可以很好地利用他们的时间。
Google的审查时间中位数比其他项目要短得多。我们假定这些差异是由于Google在代码审查方面的文化(严格的审查标准和对快速审阅时间的期望)。 此外,审稿人人数也有很大差异(其中一个在Google中,而其他两个在其他项目中);我们认为拥有一名审阅者可以使审阅变得快速而轻便。
审阅时间短和审阅者人数少可能是由于代码审阅是开发人员工作流程中必不可少的一部分;它们也可能源于小的更改。OSS项目的中位数变化范围从11到32行变化,具体取决于项目。在公司中,此更改大小通常较大,有时高达263行。我们发现Google的更改大小与OSS更接近:大多数更改很小。变更的大小分布是代码审查过程质量的重要因素。先前的研究发现,随着更改大小的增加,有用评论的数量会减少,审阅延迟会增加。大小也会影响开发人员对代码审查过程的理解;Mozilla投稿人的调查发现,开发人员认为与大小相关的因素对审核延迟的影响最大。Google确认变更大小与评论质量之间的相关性,并强烈鼓励开发人员进行小的增量更改(大删除和自动重构除外)。这些发现和我们的研究支持审查小的更改的价值以及对研究和工具的需求,以帮助开发人员创建如此小的独立代码更改以进行审查。
7.2 实践中的软件工程研究
Google进行代码审查的部分做法与软件工程研究中提出的做法保持一致。例如,微软公司对代码所有权的一项研究发现,应认真审查较小贡献者所做的更改,以提高代码质量。我们发现,此概念是在Google上通过要求所有者批准而强制实施的。同样,以前的研究表明,通常有一个变更的审阅者将负责检查代码是否符合常规。可读性使此过程更加明确。在下文中,我们将重点介绍使其成为“下一代代码审查工具” 的CRITIQUE的功能。
审查者的建议。研究人员发现,对审稿代码具有先验知识的审稿人会提供更多有用的评论,因此工具可以为审稿人选择提供支持。我们已经看到,审阅者推荐功能受工具支持,从而优先考虑那些最近编辑/审阅受审文件的人员。这证实了最近的研究,即频繁的审稿人对模块的发展做出了巨大的贡献,应与频繁的编辑者一并纳入。在Google中,实际上,找到合适的审稿人似乎没有问题,实际上,实施推荐的模型很简单,因为它可以以编程方式识别所有者。这与其他用于标识审阅者的提议的工具相反,审阅者已经审阅了具有相似名称的文件或考虑了诸如审阅中包含的评论数量之类的功能。Google的工作重点是处理审稿人的工作量和暂时缺勤(与Microsoft的研究一致)。
静态分析集成。对88位Mozilla开发人员进行的定性研究发现,静态分析集成是代码审查最常用的功能。自动进行的分析使审阅者可以专注于更改的可理解性和可维护性,而不会因为琐碎的评论(例如关于格式)而分心。我们在Google的调查向我们展示了在代码审阅工具中进行静态分析集成的实际含义。CRITIQUE为分析作者集成了反馈渠道:审阅者可以选择在分析生成的评论上单击“请修复”,以表示作者应修复该问题,作者或审稿人都可以单击“无用”以标记对审阅过程无用的分析结果。具有较高“无用”点击率的分析仪已固定或禁用。我们发现,这种反馈循环对于维持开发人员对分析结果的信任至关重要。
协作审查之外的审查工具。最后,我们找到了有力的证据,表明CRITIQUE的使用超出了审查代码。变更作者使用CRITIQUE来检查差异并浏览分析工具的结果。在某些情况下,代码审查是变更开发过程的一部分:一个审查者可能会发送未完成的变更,以便决定如何完成实施。此外,开发人员还使用CRITIQUE来检查提交的更改的历史,只要这些更改被批准即可。这与Sutherland和Venolia设想的将代码审查数据用于开发的有益用法相一致。将来的工作可以调查代码审查工具的这些意外的和潜在的有影响的非审查使用。
7.3 知识传播
知识转移是Rigby和Bird提出的主题。为了衡量由于代码审查而导致的知识转移,他们从先验工作的角度出发,通过测量变更,审查和两个集合的不同文件数来衡量专业知识,以更改的文件数为依据 。他们发现开发人员通过代码审查了解更多文件。
在Google,知识转移是代码审查教育动机的一部分。我们试图通过查看评论和编辑/审阅的文件来量化此效果。随着开发人员积累了在Google工作的经验,他们对其更改发表的评论平均减少了(图2)。在过去一年内开始工作的Google开发人员,每次更改的注释通常多于两倍。先前的工作发现,作者认为来自审阅者的注释无用,而无用注释的数目则随着经验的增加而减少。我们假设评论的减少是由于审阅者在使用代码库建立谱系关系时需要询问较少的问题的结果,并佐证了代码审阅的教育方面可能随着时间的流逝而得到回报的假说。此外,我们可以看到, 由Google的工程师编辑和审查的文件,以及这两个集合的结合,随着资历的增加而增加(图3),并且看到的文件总数明显大于编辑的文件数。在公司工作(以3个月为增量),然后计算他们已编辑和审阅的文件数。在以后的工作中,更好地了解审阅文件如何影响开发人员的流利性将是很有意思的。
图2. 审查者的评论和开发者在Google的任职年限
图3. 全职员工随时间查看(编辑或审阅,或两者都有)的不同文件的数量。
8.结论
我们的研究发现,代码审查是Google开发工作流程的重要方面。担任所有职务的开发人员都将其视为提供多种好处的环境,并且在此上下文中,开发人员可以相互学习代码库,维护团队代码库的完整性以及搭建,建立和发展确保代码库可读性和一致性的规范。开发人员报告说,他们对审查代码的要求感到满意。大部分更改很小,只有一名审阅者,除了提交授权外没有其他评论。在一周中,有70%的更改在邮寄出去进行初审后不到24小时内就会提交。这些特征使代码审查比其他采用类似过程的项目更轻便。此外,我们发现Google在其实践中包含了一些研究思想,从而使当前研究趋势的实践意义显而易见。
本文是翻译,阅读原文:
https://dl.acm.org/doi/10.1145/3183519.3183525