您想阅读哪些案例研究主题?参与快速调查。

案例研究

  下载本文的PDF版本 PDF

CodeFlow:改进微软的代码审查流程

与 Jacek Czerwonka、Michaela Greiler、Christian Bird、Lucas Panjer 和 Terry Coatta 的讨论

您可能会想,“代码审查流程?这不是很明显吗?” 但代码审查非常普遍。任何开发人员都可能随时被要求审查别人的代码。而且您可以确信您的代码也会被审查。对于一些开发人员来说,代码审查会占用每天的一部分时间。所以答案就在这里:大量薪酬优渥的人员花费大量时间在这项活动上,这意味着总成本相当可观。如果您谈论的是像微软这样规模的开发部门,那么在代码审查方面的常规投资确实相当惊人。

这只是 Jacek Czerwonka 和他在微软的 TSE(软件工程师工具)团队着手研究代码审查流程在整个公司如何运作的原因之一。另一个原因与他们发现的一个有趣的挑战有关,即除了在软件工程集成中的重要作用外,代码审查还涉及到一些相当复杂的社会动态,这些动态难以进行简单建模。

此外,微软的代码审查工具也为接触整个公司的每位开发人员提供了机会。对于一个负责提高开发人员生产力的团队来说,这正是梦想中的杠杆。更重要的是,该工具还为 TSE 的研究人员提供了一些可以进行工具化以收集数据和生成指标的东西,而这些指标反过来又可以用于进一步的研究。

所以,这就是该团队开始这段旅程的原因。为了讲述这段旅程的经历、走向以及沿途学到的东西,Czerwonka 在这里与研究员 Michaela Greiler 和 Christian Bird 一起讨论了这项工作。Tasktop 的工程高级总监 Lucas Panjer 和 Marine Learning Systems 的 CTO Terry Coatta 也到场帮助指导讨论,Marine Learning Systems 是一家位于温哥华的初创公司,致力于开发学习平台。



LUCAS PANJER 是什么最初促使您专注于代码审查流程?

JACEK CZERWONKA 这个团队是几年前成立的,目标是鼓励整个微软采用一套通用的软件工程工具。我们在这条道路上已经走了一段时间了。我们还没有完成。但在一些地方,我们已经设法快速集中工具,其中之一就是在代码审查工具方面。

显然,在审视工程工作流程的这一方面时,我们看到已经有一些工具到位,所以我们只是专注于确定我们可以做些什么来改进。首先,我们想从实际经验中学习,因为您总是希望从扎根于实践和理论的基础开始。因此,我们开始研究我们可以获得的任何与微软已有的代码审查工具和流程相关的定性或定量数据。这就是我们开始尝试了解流程起源以及随着时间推移如何演变的旅程的开端。驱动这种演变的因素是什么?当前如何应用该流程?它如何与开源协同工作?它在微软内部如何运作?当我们发现自己与他人合作时会发生什么?

LP 您最初最终关注的是什么?

CHRISTIAN BIRD 总的来说,我们想 выяснить 是什么促使人们首先进行代码审查。通常有多少人参与?提出了哪些类型的问题?是什么导致人们做出更改?又是什么通常导致人们不做出更改?

TERRY COATTA 工程团队本身是否在推动这一调查方向?也就是说,是否有人来找您说,“我们在代码审查上花了很多时间,但似乎并没有从中获得太多好处”?

CB 主要是因为这是一个数据丰富且易于获取的领域。话虽如此,一旦人们发现我们在做什么,他们就表现得非常接受。这不像他们在怀疑我们为什么要进行这项研究。事实上,情况恰恰相反。人们普遍非常支持改进代码审查流程,如果有什么的话,他们表示希望代码审查被视为头等大事。此外,许多人非常兴奋地得知有可供他们自己跟踪的数据。

LP 一旦人们与您互动并告诉您他们认为有价值的东西,他们是否也让您知道他们还想要什么?

CB 人们最想要的是能够进行自己的跟踪,以及一种查看他们与其他团队相比做得如何的方法。我们提出了一些指标,这些指标与微软团队在软件开发过程的不同阶段想要实现的一些目标相一致。例如,他们想知道他们是否在按计划在一个月内将提交内容合并到主分支中。或者他们想看看他们是否顺利实现了 80% 的测试覆盖率。

同样,对于代码审查,一些团队有目标,而另一些团队则没有,因为他们没有衡量方法。因此,他们可能会决定,至少应该有两个人签署每次代码审查,并且每次审查都必须在 24 小时内完成。在我们开始收集有关代码审查的数据、分析数据,然后使其更普遍可用之前,团队无法衡量这一点。然而,他们想要能够做到这一点,因为他们已经在衡量开发过程的其他部分。结果,人们开始告诉我们他们会发现哪些指标有用。然后我们只需将这些指标添加到我们已经收集的指标中。事实证明,我们的大部分努力实际上是由开发团队自己告诉我们他们希望能够衡量的东西驱动的。

TC 既然您说现在微软的每个人都在使用这种代码审查工具,您能否简要描述一下它提供的功能,以及您认为这些功能与微软以外的大多数人可用的功能相比如何?

JC 嗯,我们现在谈论的是几年前我们用我们的工具(名为 CodeFlow)做的事情,而且在这么长时间内,工具在世界各地有一种趋同的方式。因此,我们当时所做的一些更改现在对于使用其他后来以大致相同方式工作的代码审查工具的人来说可能看起来相当明显。

简要总结是,我们对底层子系统进行了一些更改,以进行微调。我们还训练该工具在跟踪更改方面非常精确,因为人们会经历大量的软件迭代。也就是说,当您从一个修订版本移动到下一个修订版本时,您可以想象您的代码更改最终会四处移动,因为一些代码被删除,一些新行被添加,并且代码块被重新排列。这可能会使您的注释跟踪与您最初的意图严重不同步。克服这个问题需要付出努力,但我们现在从反馈中得知,它受到了极大的赞赏,因此非常值得付出努力。

我们关注的另一件事是性能。出于这个原因,即使在今天,CodeFlow 仍然是一个客户端工具,这意味着您可以先下载您的更改,然后再与之交互,这使得在文件和不同区域之间切换非常非常快。

CodeFlow 基本上已在整个微软普及,这也很有帮助。这是因为我们使用了类似于病毒式营销策略的方法,即当您被添加为审查者时,您会收到通知,这使您只需单击链接即可打开审查。然后将安装 CodeFlow 客户端并打开审查。因此,在该工具被引入到一个小组后不久,它就会开始在团队结构中自行渗透。不要求为 CodeFlow 进行特殊安装的选择被证明是非常好的。

LP 从用户的角度来看,CodeFlow 与 Git 或 Gerrit 有什么特别的区别吗?您会如何说它与您在拉取请求和基于补丁集工具中发现的不同?

CB 归根结底,它是一个原生应用程序,而不是 Web 功能,这意味着它可以实现比您原本获得的更丰富的交互。我经历过 Git 和拉取请求的东西,绝对可以轻松地从一个评论跳转到另一个评论,并且您还可以获得像评分框一样的东西。也就是说,它们感觉像丰富的原生客户端,所以我意识到您可以使用 Web 体验来实现这一点。

至于 Git 和 Gerrit 代码审查,您在那里获得的只是一些差异列表。我的意思是,您也可以添加评论,但是,最终,这只会使跟踪事物或有效地导航所有内容变得更加困难。

因此,CodeFlow 是原生的并且像桌面上的头等大事一样对待这一事实使其更易于使用。

MICHAELA GREILER 我也非常喜欢 CodeFlow 评论功能的丰富性。例如,您可以仅标记一行代码中的单个字符,而不是调用整行代码。这样,人们可以立即看到问题的确切位置。此外,直到今天,很少有代码审查工具允许您跨越区域,但是使用 CodeFlow,您可以同时将评论附加到多个已删除的行和插入的行,然后通过后续迭代跟踪所有这些内容。另一个值得指出的功能是评论线程,它使您可以同时解决整个评论线程,而不是单独处理每个评论。



代码审查通常会让人联想到故障排除的概念。更具体地说,人们倾向于将它们与永无止境的搜索错误联系起来。

事实证明,这远没有您想象的那么重要。这并不是说发现错误不重要或不受鼓励。然而,真正的胜利似乎是以改进长期代码可维护性的形式出现的。



LP 您决定首先解决哪些问题?

JC 我们选择关注的大多数问题都是面向流程的。该工具本身非常灵活,几乎可以适应任何流程。我们花了很多时间试图了解代码审查的好处以及阻碍实现这些优势的因素。此外,我们想了解现有代码审查工具的使用情况。我们有兴趣更多地了解成本和周转时间,希望我们能够更好地了解驱动因素。

MG 此外,我们研究的问题之一是如何创建审查者推荐器,因为程序员一直在向我们抱怨找到合适的人来审查他们的代码有多么困难。Chris 开始开发一个工具,该工具将提供一份具有与您的代码解决的各种问题相匹配的专业知识的人员列表,以及关于您可能想要添加到审查中的哪些人的建议。

Chris 和我还花了一段时间研究代码审查的有用性。当然,这不是我们试图解决的问题,但我们确实想了解代码审查的哪些方面往往最受工程师的重视,也就是说,审查者和程序员都重视哪些方面。他们认为什么最有用?我们很快得出结论,审查者感兴趣的不是接受或修改代码的简单决定,而是增加了审查价值的评论。另一方面,一些评论只会增加代码审查的负担并减慢开发过程。因此,我们想知道他们发现哪些类型的评论最有用,因为我们可以开始考虑如何鼓励和更加重视这些评论。

JC 正如这个关于有用性的有趣问题后来导致了实际意义一样,也可以对为研究其他与流程相关的问题所做的工作说同样的话。例如,您应该在代码审查中包含多少人?是否存在一个超出该数字就会适得其反的数字?我们都凭直觉感到较小的审查更好,但确切的界限在哪里?以及允许审查的最佳时间量是多少?

MG 我们发现的另一个有趣的事情是,虽然流行的观点是代码审查主要用于查找错误,但我们研究的代码审查评论中只有很小一部分实际上与错误有关。事实上,大多数评论都与结构问题和样式问题有关。有时它们甚至与非常小的问题有关,例如拼写。基本上,我们发现许多审查者都在使用他们的评论平台来讨论这些问题并分享他们的知识。

我们发现对这些评论进行分类并进行一些映射以确定哪些评论被认为是最有趣或最有用的评论非常具有启发性。事实证明,通常证明是对识别功能问题、指出缺少验证检查或提供与 API 使用或最佳实践相关的建议的评论。

LP 仅供参考,您能否也谈谈这项研究的规模——您正在使用的代码库的大小、您分析的代码审查的数量或参与的开发人员的数量?

CB 我们进行了许多不同的研究,其中许多研究比观察性研究更定量。在一个案例中,我们进行了一项初步研究,结果表明,某人对某段代码的知识深度肯定会体现在他们作为审查者能够提供的反馈质量中。也就是说,要获得更高质量的评论,您需要来自对特定软件有一定经验的人的审查。然后,为了检验该结论,我们与一些工程师进行了交谈和观察,这些工程师提交了他们已经熟悉的代码的审查。我们还观察了一些被要求审查他们以前没有经验的代码的工程师。那是一项小型研究,但它给我们留下了一些明确的印象。

还有 Michaela 刚才提到的那些研究,我们考虑了评论的有用性。这是基于从整个微软收集的数据,然后输入到我们构建的机器学习分类器中以对代码审查进行分类。我们最终使用它来分类 300 万次代码审查,这些代码审查是由数万名开发人员编写的,并来自整个微软的每个代码库——这意味着我们很容易谈论数亿行代码。显然,我们能够在那里执行的定量数据分析是基于大量数据的。另一方面,定性观察性研究通常规模要小得多。

MG 我们绝对拥有大量可用的数据——基本上是为 Office、Windows、Windows Phone、Azure 和 Visual Studio 以及许多较小项目编写的所有代码。

JC 我们在微软也享有优势,因为我们有如此多的不同产品类型。我们关注人们在操作系统、应用程序、大型服务、小型服务以及介于两者之间的一切方面所做的工作。我们非常清楚这些领域中每个领域的不同需求,并且我们在进行研究时会特别注意这一点。

LP 在您可以从 CodeFlow 的使用中获取数据的那些情况下,您是否也能够进一步工具化该工具以增强您的研究?

JC 从工具化 CodeFlow 中浮现出来的最有趣的事情之一是人们在审查工具中积极花费了多少时间。这是因为我们发现人们经常会打开该工具的多个实例,然后在他们获得一点空闲时间时,在这里进行一次小型审查,然后在那里进行另一次小型审查。因此,仅仅因为您可以看到该工具已打开了一段时间,并不意味着您可以假设在整个时间内都有活动。我们有遥测技术来确定您在应用程序内导航了多长时间。这使我们能够确定,平均而言,人们每天在 CodeFlow 中积极工作大约 20 分钟——一旦您将此数字乘以 40,000 人,这将是一个相当长的时间。

CB 从这一切中,我们已经能够提出许多一般性意见,我们总是很乐意将这些意见作为建议传递出去。事实上,我向任何希望做类似于我们在分析自己组织的代码审查流程中所做的事情的人提出的一个建议是,在考虑收集哪些数据时,尽可能接近应用程序本身采用的实际对象模型。例如,我们的数据库中的表与应用程序中的类几乎存在 1:1 的对应关系。因此,我们不必过多考虑是否要收集某些东西。我们只是抓取了一切。

因此,我们最终收集了所有这些原始数据,这样做的一个好处是,即使您没有立即看到某些数据的需求,您也可能会在以后的新研究中找到它的用途。这意味着您不会面临需要返回并更新您的数据收集系统以提供该数据的困境。缺点是您还将拥有所有这些尚未处理以供使用的原始信息,这意味着稍后会有一些工程师来构建一个指标层,使其位于所有这些信息之上。这将使您拥有两个级别的数据——分析层和另一个包含原始对象模型数据的层——如果人们希望真正深入了解,则可以稍后深入研究。

事实证明,这种分层对我们来说是一个非常明智的举动,因为我们现在不仅可以迎合只想查看指标和审查的普通用户,还可以迎合想要深入研究事物的人。

LP 您是说在您创建了这些用于研究目的的工具之后,其他团队将继续使用它们来反思他们自己的流程吗?

CB 是的。事实上,我们在几年前进行了一项研究,我们联系了一些使用我们数据的团队,以 выяснить 他们究竟在用这些数据做什么,以及看看他们是否设法以任何方式改进了流程。我们认为这可能是 выяснить 我们需要在哪里进行自己的研究的一种方法。

我们发现一些团队正在使用这些数据来生成记分卡,而另一些团队则使用这些数据来 выяснить 人们在理解代码库时遇到问题的地方,然后使用这些见解来推动他们的培训计划。我们最终与至少十几个其他团队进行了交谈,并且令人感兴趣和惊讶的是,了解了其中一些团队使用我们数据的不同方式。

LP 有哪些更大的惊喜?

CB 对我来说最大的惊喜是得知一些团队会使用我们的工具来识别耗时过长或只包含少量评论的代码审查。然后,他们会根据这些数据打开代码审查,并且审查会告诉他们使用了什么代码以及正在审查代码的哪个部分。他们会深入研究并迅速确定,“哦,看起来人们在审查使用这个特定 API 的代码时遇到了困难。” 这就是他们如何确定他们的下一次培训课程应该专门针对该 API 的原因。

TC 您是否开发了任何用于评估代码审查质量的指标?

CB 没有,但据我所知,一些团队已经围绕这些数据构建了实时仪表板。一些开发团队在墙上安装了一个巨大的电视显示器,可以在其中显示“自上次错误以来的时间”或“下次发布的交付时间”等指标。一个团队告诉我们,他们还将代码审查数据放在他们的记分牌上,以便人们可以看到有多少代码审查积压或完成代码审查平均需要多少时间。从他们告诉我们的情况来看,将这些数据放在实时仪表板上,任务控制风格,已被证明非常具有激励作用。



从一开始,为管理和改进微软的代码审查流程提供一套新的功能就是首要目标。在完成该目标的过程中,还了解了很多关于某些通用代码审查原则的知识——这些原则也可能在其他地方得到有益的应用。事实上,随后的研究提供了令人惊讶的证据,证明当许多公司遵循这些原则时,其影响可能与其他公司(或开源项目)的影响非常相似。



LP 回顾您刚开始这个项目的时候,您会说每当您询问人们进行代码审查的主要动机时,最常出现的是什么?

MG 我们进行了一项调查,要求人们对他们的理由进行排名。结果往往很明显:改进代码、查找缺陷、知识转移等等。但是,当我们启动另一项研究来分类实际代码中留下的评论时,我们发现它们很少与那些陈述的动机相符。

LP 有趣。这些评论主要关注什么?

MG 当然,有很多关于文档的评论。您会看到一些与替代解决方案有关的评论。还有一些关于验证的评论,这确实倾向于错误解决的方向,因为人们会说,“你知道,如果这个特定的角落案例消失了,你就可以消除其中的一些问题。” 人们还会对 API 的使用以及最佳实践发表意见。总的来说,我想说这些类型的评论远远超过了任何关注特定缺陷的评论。

JC 关于 Michaela 提出的期望与现实不符的观点,尽管人们一直表示他们进行代码审查的主要原因是发现代码中的错误,但我们发现的代码中只有 15% 的评论实际上与错误有关。例如,我们会发现关于控制流问题或错误使用 API 的评论——甚至是以错误的方式使用正确的 API。另一方面,至少一半的评论是关于可维护性的。因此,对于审查者本身而言,识别可维护性问题似乎比发现错误更重要。

LP 既然您的工作已经进行了多年,您在所有不同的开发团队中看到了哪些类型的代码审查政策和实践影响?

JC 我们的首要目标之一是减少平均完成代码审查所需的时间。我们希望 выяснить 人们似乎在哪些地方花费了过多的时间,这就是导致创建审查者推荐器的原因。这真是一件很简单的事情,但如果您是一个大型团队的一员,可能很难找到具有合适经验的人。拥有一个自动化系统来识别那些对某些更改所在的文件有所了解的工程师,可以帮助减少审查这些更改所需的时间。

我们最近还做了一些事情,就是让开发人员能够解释他们试图完成的事情。这是因为我们经常听到审查者的抱怨,即理解代码更改背后的原因可能非常具有挑战性。也就是说,他们希望找到某种方法来了解做出更改的人的心态,以便他们更好地理解更改实际上是否有意义。

处理这个问题的一种方法是显示不仅仅是进行更改的代码的隔离部分。相反,我们显示整个文件,以便审查者可以更好地了解每次更改周围的代码。我们还希望为更改的作者提供一些手段来提供更多信息,以便审查者可以更好地理解他们的理由。为此,我们的系统现在允许作者在文件和区域上放置标签,以指示哪些文件是更改的核心,因此可能应该特别关注。例如,标签可以用来快速指示对测试用例而不是产品代码进行了哪些更改。或者它们可以用来指出某些具有潜在安全隐患的文件或更改。

LP 你们还有其他正在开发的新功能吗?

JC 我们试图解决的根本潜在因素是代码审查的大小,因为这会影响生成审查所需的时间以及从中产生的评论的有用性。这是一个难以解决的问题,因为一些问题本质上是文化性的,而另一些问题则与工作流程有关。尽管如此,有时两个不相关的关注点最终会被塞进一次审查中,因此我们希望我们能够通过自动将这些关注点拆分为两次较小的审查来理清一些审查。平均而言,这应该会导致更好的周转时间和更好的结果。

LP 您是否采取任何措施让开发团队将他们的代码审查时间集中在正确性和内容而不是样式上?是否已实施任何工具更改或流程更改以实现该目标?

JC 我们没有对此进行适当的研究,但这里有一个团队在这方面做了一些事情。这与他们认为低风险的一些重构更改有关——例如重命名方法或局部变量。例如,这可能涉及在审查上放置一个特殊标签,说明“我们真的不需要两个人来查看这个。一个就足够了,因为我们不太可能在这里遇到任何功能问题。” 尽管这看起来可能很不起眼,但它也可能被证明是意义深远的,因为事实证明,有许多这样的更改在遗留系统中浮动——阻塞系统。

要记住的是,这不仅仅是让一次更改更快地进行,因为您在这里处理的是更改管道——这意味着您可以重定向到更轻量级路径的任何更改都将降低关键人员的负载,并使其不妨碍其他等待审查的更改。这正是使整个系统更有效率的原因。

TC 考虑到微软以外没有您的工具的人,您从您的经验中有哪些建议可能具有相关性?

JC 我想说,要认识到的一件事是,与可维护性相关的评论主要是您将从代码审查过程中获得的东西。与流行的观点相反,查找错误不是主要结果。另一个要记住的重要事项是,审查越小,效果就越好。在我们的案例中,我们发现,如果审查包含超过 20 个文件,那就已经太大了。事实上,根据我们对我们掌握的所有数据的研究,我们得出结论,对于超过 20 个文件,评论的密度和有用性会显着降低。这实际上更像是一个经验法则,而不是一个精确的限制,但记住它很有用。

此外,如果您的组织有来自过去审查的数据,我建议投资于一个推荐系统,该系统可以帮助使一些管理步骤不那么繁琐。您甚至可以使用这些系统来自动解决您的一些可维护性问题,这是我们现在开始涉足的领域。也就是说,您可以想象,其中一些可维护性问题本质上可能是可以自动发现和标记的东西,这意味着您无需花费任何人力资源来完成这项工作。

正如我们刚才讨论的那样,另一件事是,对每次更改进行两次签名可能太多了。如果您查看第一个或第二个审查者提出的评论的分布情况,您会发现您的第一个审查者通常会发现最令人发指的问题。在许多情况下,在允许提交到主源代码树之前,等待第二个审查者证实这些发现可能效率较低。

MG 我从调查中获得的最大收获是始终尽可能地减少代码审查的负担。其中一部分归结为拥有一个良好的代码审查流程,该流程能够实现和鼓励易于审查的评论。

另一个重要的考虑因素与支持审查者本身有关,即提前通知他们任何可能即将到来的审查,并为他们提供足够的背景信息,以便他们能够直接投入到审查中,而不必自己 выяснить 所有这些信息。尽您所能减少审查规模也可能有所帮助。但我认为真正重要的是使审查尽可能简单,否则,您最终可能会遇到不知道从哪里开始的审查者。

此外,组织需要表明他们认识到代码审查的价值,因为毫无疑问,代码审查会占用开发人员原本可以用来创建代码的时间。如果开发人员仅因添加功能而获得奖励,那么最终将削弱代码审查流程,这反过来几乎肯定会对生成的代码的可维护性产生不利影响。

CB 我想补充一点,我们现在在微软拥有的代码审查流程或多或少是从基层通过实验有机地发展起来的。我提到这一点只是因为我认为它也可能适用于较小的公司,而不是从上到下强制执行的某些流程。

此外,微软的每个产品组的代码审查方式都略有不同,每个组都使用自己的一套基本上是有机地结合在一起的政策。虽然这可能不会成为一个开创性的启示,但绝对可以说,代码审查没有一刀切的解决方案。这只能进一步强调愿意让您的方法有机地演变的重要性,使其最终能够以最小的摩擦适应您的工作流程,同时尽可能减轻开发人员的负担。

另一个重点是 Michaela 之前谈到的内容,即将代码审查视为头等大事——就像许多公司可能对待测试一样——可能是获得最大收益的最佳方式。相反,如果它变成您只是被期望做的事情,就像每天用牙线清洁牙齿一样,那么您会发现人们不会接受它。但是,如果您说这很重要,因此将被跟踪和评估,那么人们可能会对此做出回应。当然,这就是它在这里的工作方式。

而且,我想补充的另一点是,深入思考一下你真正希望从代码审查中获得什么,这是很有启发意义的。当然,你也应该考虑如何衡量它。在你可以跟踪这些指标并设定目标的程度上,你总是会取得更多成就。



相关文章

使用免费和开源工具来管理软件质量
一种敏捷流程的实施
Phelim Dowling 和 Kevin McGrath,电信软件与系统组
https://queue.org.cn/detail.cfm?id=2767182

案例研究 - LinkedIn 的 Node:追求更薄、更轻、更快
与 Kiran Prasad、Kelly Norton 和 Terry Coatta 的讨论
https://queue.org.cn/detail.cfm?ref=rss&id=2567673

与 Steve Bourne、Eric Allman 和 Bryan Cantrill 的对话
在他们讨论的第二部分中,我们的编委会成员考虑了 XP 和敏捷。
https://queue.org.cn/detail.cfm?id=1454460



版权 © 2018 由所有者/作者持有。出版权已授权给 。

acmqueue

最初发表于 Queue 杂志第 16 卷,第 5 期
数字图书馆 中评论这篇文章








© 保留所有权利。

© . All rights reserved.