2. 计算机科学国家重点实验室(中国科学院 软件研究所), 北京 100190;
3. 中国科学院大学, 北京 100049
2. State Key Laboratory of Computer Science (Institute of Software, Chinese Academy of Sciences), Beijing 100190, China;
3. University of Chinese Academy of Sciences, Beijing 100049, China
同行代码评审, 即对提交代码进行人工评审, 已被证明是减少软件缺陷和提高软件质量的有效手段.近年来, 现代代码评审(modern code review)[1], 一种轻量级的同行代码评审实践, 已经被业界各公司(如微软、谷歌)和各大开源社区广泛采用.例如, GitHub提供了一个在线评审流程: 项目的贡献者(contributor)可以通过添加新特性或修复某些bug来对源代码进行一定程度的更改, 但是更改不能直接提交给项目基线库, 而是以合并请求(pull request)的形式提交给社区.每一个合并请求的创建就代表需要进行一次代码评审(code review), 每个贡献者都可以是潜在的评审人员, 可以在代码风格、新特性的必要性、代码逻辑的正确性等方面对该合并请求留下评论(comment).最后, 项目集成人员在综合考虑所有评审人员的意见后, 做出是否接受合并的决定, 以确保来自贡献者的代码质量.该评审流程是GitHub社区pull-based软件开发模型的重要组成部分, 确保了来自贡献者的代码质量[2, 3].
对于一些受欢迎的GitHub项目, 贡献者数量常常会达到千人以上规模, 并因此提交了大量的合并请求, 然而大多数合并请求不能及时得到评审[3].根据Gousios等人的调查结果, 15%的贡献者抱怨合并请求没有在他们预期时间内被处理[4].进一步, Thongtanunam等人的研究表明, 没有找到合适代码评审人的合并请求比其他合并请求需要多12d才能被批准[5].此外, 在一个项目中有成百上千个候选评审人员, 这更加剧了代码评审人推荐问题的难度.因此, 为了提高代码评审的质量和效率, 迫切需要有效的评审人员推荐方法.
近年来, 代码评审人推荐的研究备受关注.Balachandrany、Thongtanunam、Hannebauer等人设计启发式规则, 基于历史提交和评审信息抽取得到的评审人修改经验和评审经验来进行人员推荐[5-7]; Jeoung、Lipcak等人通过抽取代码修改内容等提取特征, 使用机器学习和信息检索方法来推荐评审人员[8, 9]; Yu等人基于开发者在代码提交和评论中的交互, 通过社会网络方法进行人员推荐[10]; Xia等人混合以上两种或多种方法, 进一步优化评审人推荐的效果[11-13].以上研究均以能否找到合适的评审人为目标, 忽略了评审响应时间这个重要因素.评审响应时间是指代码评审创建与评审人来参加评审(表现为在评审中留下评论)的时间间隔.
由于开源项目的社会自治性, 实际的项目开发实践中, 评审人的响应时间过长是制约项目进展和代码提交者积极性的重要因素[3, 4, 14].当一次提交经过相当长的时间后依然没有收到任何回复信息, 该提交的贡献者会有更大的可能性脱离该项目贡献者团队.我们基于6个开源项目的数据统计发现, 平均15.3%~63.2%的合并请求在72h内没有响应, 平均24%~68.4%的合并请求在24h内没有响应.已有的仅以寻找合适评审人为目标的代码评审人推荐方法[5-7, 8-13]并不能解决响应时间的问题.
为此, 本文提出响应时间约束的代码评审人推荐问题, 即推荐的评审人能否在约定时间内进行评审, 目标是推荐合适的代码评审人在更短的时间内完成代码评审, 从而进一步提升代码评审的效能, 促进开源社区参与人员的积极性.“合适的代码评审人”是沿用已有研究[5, 8, 10, 11]的说法, 仅指该评审人是否进行代码评审, 不考虑评审的响应时间.
进一步, 我们提出了基于多目标优化的代码评审人推荐算法(MOC2R).该方法通过最大化代码评审人经验、最大化在约定时间内的响应概率、最大化人员最近时间内的活跃性这3个目标, 使用多目标优化算法来推荐代码评审人员.我们基于6个开源项目的数据进行实验验证, 结果表明, 在不同时间窗约束下(2h、4h、8h), Top-1准确率为41.7%~61.5%, Top-3准确率为58.4%~74.9%, Top-5准确率为66.5%~77.7%, MRR为0.53~ 0.58.与基线方法相比, 平均Top-1准确性提高了81%~143%, 平均MRR提升了56%~97%.此外, 我们还实验评估了每个目标对于评审人推荐的贡献, 发现3个目标缺一不可, 其中, 约定时间内的响应概率目标对于人员推荐的贡献最大.
本文贡献在于:
1) 我们基于真实开源项目数据分析了当前代码评审响应时间的现状, 提出了响应时间约束的代码评审人推荐问题.
2) 我们提出了基于多目标优化的代码评审人推荐算法, 可以最大化代码评审人经验、最大化在约定时间内的响应概率、最大化人员最近时间内的活跃性.
3) 我们在GitHub的6个大型项目评估了方法的效果, 并得到了很好结果.
本文第1节进行问题分析.第2节提出基于多目标优化的代码评审人推荐算法.第3节和第4节给出相关实验的设计方法和实验结果分析.第5节作进一步讨论.第6节回顾代码评审人推荐的相关研究工作.最后, 在第7节进行总结.
1 问题分析本节基于真实的开源项目数据, 分析当前代码评审响应时间的现状以及代码评审的人员属性.
1.1 合并请求响应时间分析我们基于GitHubd的6个流行的开源项目(详见第3.3节), 对历史合并请求的响应时间进行了统计, 结果见表 1.
![]() |
Table 1 Pull request response time 表 1 合并请求响应时间 |
6个项目中, 平均有15.3%~63.2%的合并请求在72h内没有响应, 24%~68.4%的合并请求在24h内没有响应.其中, flutter/flutter是合并请求响应时间最快的项目, 有52%的合并请求在2h内得到响应.而ohmyzsh/ohmyzsh是合并请求响应时间最慢的项目, 超过60%的合并请求在24h内不能得到回复.进一步地, 我们统计了flutter/flutter和ohmyzsh/ohmyzsh两个项目在2015年~2019年中每年3月1日的文件个数(NOF)和代码行数(LOC), 见表 2.flutter/flutter代码规模增长速度明显领先于ohmyzsh/ohmyzsh.其在2018年3月~2019年3月代码规模增长了近1倍(33万行代码增长至近60万行代码), 而ohmyzsh/ohmyzsh在5年时间内代码规模增长不足1倍(1.7万行增长至2.9万行).
![]() |
Table 2 Code size in flutter and ohmyzsh 表 2 Flutter与ohmyzsh代码规模 |
根据谷歌工程实践文档, 代码评审最长需要在一个工作日进行反馈[15].以上数据和分析说明, 在开源社区的代码评审实践中, 存在很多的合并请求不能及时得到响应的情况.这种情况存在的原因有很多, 例如, 由于每日提交的合并请求数量过多, 导致部分请求难以得到及时处理[16], 像flutter/flutter项目平均每周接收到85个合并请求; 再如, 由于不知道谁是合适的代码评审人, 使得合并请求停留在评审人分派阶段, 没有在预期的时间内处理[5]; 或者即使已经分派给某个代码评审人后, 由于不合适的分派导致的评审时间过长, 例如评审人经验不匹配、或评审人没有足够时间[1, 4], 这延长了评审周期、降低了参与人员的积极性和项目的发展速度.因此, 本文提出响应时间约束的代码评审人推荐问题, 即推荐的评审人能否在约定时间内进行评审, 目标是为代码评审推荐合适且响应速度快的评审人, 加速评审过程, 提升社区活跃性.
1.2 人员响应时间分析图 1给出flutter/fluttert和ohmyzsh/ohmyzsh两个项目的代码评审人的响应时间分布, 其他项目的趋势和这两个项目相同, 篇幅限制不再列出.
![]() |
Fig. 1 Code reviewer average response time 图 1 代码评审人的平均响应时间 |
从图 1可以看出, 项目中不同代码评审人的平均响应时间存在很大差异.例如, 在flutter/flutter项目中, 响应时间为0.02h~912.7d, 有6.7%的评审人的平均响应时间小于2h, 有10.9%的评审人的平均响应时间大于3个月; ohmyzsh/ohmyzsh项目中, 83.7%的评审人的平均响应时间大约1d.
已有研究[1, 4]指出, 快速响应是pull-based开发模型中支持贡献的关键组成部分.快速的响应能够很好地鼓励开源项目贡献者, 有效地减少新贡献者加入项目的障碍; 相反, 代码贡献者往往都会对迟迟无法得到评审人响应而担忧, 甚至影响他们后续对项目的参与和贡献.对于那些响应很慢的评审人, 即便他们有经验、有能力, 他们的评审结果对于待评审的代码, 也是远水不解近渴, 不能及时有效地帮助项目管理者了解代码质量, 或者帮助开发人员改进质量.所以, 需要将响应时间纳入评审人推荐问题中, 考虑评审人在历史代码评审中的响应时间, 以便推荐出响应速度快的代码评审人.
1.3 人员活跃性分析我们取2018年1月~2019年1月的评审数据, 按照每半月为一个区间(作为横坐标的24个时间区间), 统计该区间上某代码评审人是否有评审活动, 有评审活动记为1, 没有评审活动记为0(作为纵坐标).图 2给出了flutter/flutter和ohmyzsh/ohmyzsh两个项目上随机选取的6个评审人员的活动情况, 其他项目的趋势和这两个项目相同, 篇幅限制不再列出.
![]() |
Fig. 2 Review activity distribution of code reviewer 图 2 代码评审人的评审活动分布 |
从图 2可以看出, 绝大多数代码评审人并不是一直活跃的, 他们会有很多不活跃的时间.如果在这些不活跃的时间推荐给他们评审任务, 则他们进行评审的响应时间会非常长, 或者说响应的概率很小.因此, 考虑评审人在最近时间内的活跃情况, 有助于找到合适且响应速度快的代码评审人.
1.4 多特征对比分析从上面两节分析中我们发现, 在进行评审人推荐时, 需要考虑人员响应时间和活跃性两个特征; 同时, 已有研究指出, 人员经验会影响评审人推荐的效果.本节进一步分析基于各自特征得到的代码评审人是否存在重合, 从而启发我们的方法设计.
我们取flutter/flutter和ohmyzsh/ohmyzsh两个项目中的全部数据, 分别基于平均响应时间、活跃性(即最近一次参加评审的时间)和历史评审总次数(表征人员经验)这3个特征进行统计, 并得到基于各自特征的评审人排序.图 3给出了不同特征下前10个评审人的交叠情况.
![]() |
Fig. 3 Personnel overlapping diagram based on respective characteristics 图 3 基于各自特征的人员交叠图 |
从图中可以看出, 基于各自特征推荐的代码评审人基本不存在重叠.具体来说, 平均响应时间最快的10个评审人与其他两个特征的前10名均未有交叠.在活跃性最高和评审总次数最多的统计结果中, flutter/flutter和onmyzsh/ohmyzsh仅有两个评审人交叠.
这说明, 3个特征需要同时进行考虑, 才能推荐出既合适又能在更短时间内完成评审的代码评审人.因此, 我们将采用多目标优化方法进行推荐.
2 MOC2R: 基于多目标优化的代码评审人推荐前面的分析和实验表明, 代码评审人在历史代码评审中的响应速度、最近时间内的活跃性均会影响他们是否及时进行代码评审: 历史响应速度表征评审人的工作习惯, 响应速度快的评审人未来也可能快速完成评审; 活跃性表征评审人参加待评审任务的可能性, 近期活跃的评审人更有可能快速完成评审.已有研究已经指出, 评审人对于待评审任务的经验会影响代码推荐效果[5-7].因此, 这3个方面需要同时考虑, 以便找到合适且响应速度快的代码评审人.
本文提出的基于多目标优化的代码评审人推荐方法MOC2R(multi-objective code reviewer recommendation), 以最大化代码评审人的经验、最大化代码评审人在约定时间内的响应概率、最大化所推荐人员最近时间内的活跃性为优化目标, 将代码评审人推荐问题建模成多目标优化问题, 建立基于多目标优化的推荐模型.MOC2R方法框架如图 4所示.
![]() |
Fig. 4 MOC2R method framework 图 4 MOC2R方法框架 |
第2.1节定义了代码评审相关的基本元素.由于多目标优化方法最重要的是优化目标的度量, 第2.2节给出了优化目标的度量方法, 第2.3节对MOC2R中如何使用多目标优化进行了介绍.
2.1 基本元素和定义图 5给出了评审历史、候选评审人、新代码评审的示意图.
![]() |
Fig. 5 Diagram for code review 图 5 代码评审示意图 |
在GitHub的开源项目中, 贡献者(contributor)每一次提交代码都需要创建一个合并请求(pull request), 每一个合并请求的创建, 就代表需要进行一次代码评审(code review).任何一个在合并请求中添加了评论信息(comment)的贡献者, 我们都视为是这次代码评审的评审人员(reviewer).
代码评审历史是指过去已经完成的一系列代码评审的合集, 表示为R={r1, r2, …, rn}, 其中, ri表示已经完成的第i次代码评审.
对于一次已完成的代码评审r, 包括其创建时间、一组被评审的变更文件以及所有参加过这次代码评审的评审人, 表示为r={createTime(r), Files(r), Reviewer(r)}, 其中, createTime(r)表示代码评审r的创建时间, Files(r)= {f1, f2, …, fn}表示被评审的变更文件列表, Reviewer(r)={(w1, t1), (w2, t2), …, (wn, tn)}表示参加评审的评审人列表, wi表示代码评审人, ti表示该评审人参加本次代码评审并留下第1条评论的时间.某个代码评审人可能会在一个代码评审中有多次评论, 本文只记录第1条评论的时间用于目标的建模.对于后续评论的发生时间对于建模和推荐效果的影响, 将在后续工作中研究.
候选评审人是开源项目中所有的贡献者, 表示为W={w1, w2, …, wn}.
一次新代码评审包括创建时间和一组待评审的变更文件, 表示为nr={createTime(nr), Files(nr)}.
我们定义代码评审人推荐问题为: 给定一个新代码评审nr、一组候选人员W、历史代码评审集合R以及响应时间窗φ(即在φ时间内需要进行响应), 推荐目标是从候选人员W中选择出一个包含k个人员的子集S, 使得选择出来的集合S中的人员能够最大化代码评审人经验、最大化在约定时间内的响应概率、最大化人员最近时间内的活跃性.
2.2 优化目标度量MOC2R定义了如下3个优化目标.
i) 目标1:代码评审人的经验
我们基于文件路径相似算法[5]设计代码评审人相关经验的度量方法, 它的基本思想是: 相似路径中的文件具有相似的功能, 如果代码评审人在过去的评审历史中积累了评审相似代码的经验, 他们更有可能是待评审任务的合适评审人.
给定两个文件fi和fj, 其相似度定义为两个文件路径的相似程度, 计算公式如下所示:
$Similarity({f_i},{f_j}) = \frac{{PathComparison({f_i},{f_j})}}{{{{\rm{Max}}}\{ Length({f_i}),Length({f_j})\} }}$ | (1) |
其中, Length(fi)表示文件fi目录层级个数, PathComparison(fi, fj)是两个文件相同的目录层级个数.具体来说, 首先将每个文件按照目录层级拆分成两个序列, 然后计算两个序列的最长公共子序列.例如, fi的文件路径为src/ layout/android/settings/utils.java, fj的文件路径为src/com/android/settings/location/utils.java, Length(fi)的返回结果为5, Length(fj)的返回结果为6, PathComparison(fi, fj)的返回结果为4(即src, android, settings, utils.java).
基于文件相似性, 对于新评审nr, 其和历史评审ri的相似度定义为两个评审包含文件集合(Files(nr)和Files(ri))之间的相似性, 表示为
$ReviewSimilarity({r_i},nr) = \frac{{\sum\nolimits_{{f_i} \in Files({r_i}),n{f_j} \in Files(nr)} {Similarity({f_i},n{f_j})} }}{{|Files({r_i})| \times |Files(nr)|}}$ | (2) |
两次代码评审相似度越高, 表示ri中的评审人员对新评审nr中的变更文件越有经验.
对于一个评审候选人w, 其相对于待评审任务nr的经验ExpertiseScore, 定义为其历史评审中与待评审任务相似度的累积值, 计算如公式(3)所示.
$ExpertiseScorew,nr = \sum\limits_{{r_i} \in {R_w}} {ReviewSimilarity({r_i},nr)} $ | (3) |
其中, Rw表示候选人w所完成的评审任务的集合.
ⅱ) 目标2:代码评审人在约定时间内的响应概率
MOC2R方法中, 基于代码评审人在历史评审中的响应速度来度量其在约定时间内进行响应的概率.我们假设响应时间窗φ(即约定的响应时间), 代码评审人w在φ时间内响应的概率即为评审人w参加过的所有代码评审Rw中, 其响应时间在φ内的评审次数占全部评审任务的百分比.计算公式如公式(4)所示.
$ResopnseScore = \frac{{\sum\nolimits_{{r_i} \in {R_w}} {response@\varphi } }}{{|{R_w}|}}$ | (4) |
$response@\varphi = \left\{ {\begin{array}{*{20}{l}} {1,{{\rm{\;\;if\;}}}FastestResponseTime(w,{r_i}) - createTime({r_i}) < \varphi } \\ {0,{{\rm{\;if\;}}}FastestResponseTime(w,{r_i}) - createTime({r_i}) \geqslant \varphi } \end{array}} \right.$ | (5) |
其中, 在代码评审人w最快响应时间小于响应时间窗φ时, response@φ返回1;否则, 返回0.
FastestResponseTime(w, ri)则计算了代码评审人w在ri中的首次响应时间, 即w留下第1条评论的时间与ri创建时间的差值.createTime(ri)是代码评审ri的创建时间.
ⅲ) 目标3:代码评审人最近时间内的活跃性
活跃性度量候选人在最近时间内的活跃程度, 即, 在最近时间tthres内, 候选人参与过的代码评审的累计次数.累计次数越高, 代表该候选人在最近时间tthres内的表现越活跃.活跃性得分计算公式如公式(6)所示.
$ActiveScore = \sum\limits_{{r_i} \in {R_w}} {active@{t_{{{\rm{thres}}}}}} $ | (6) |
$active@{t_{{{\rm{thres}}}}} = \left\{ {\begin{array}{*{20}{l}} {1,{{\rm{\;\;if\;}}}Now - {t_{{{\rm{thres}}}}} \leqslant {t_i} < Now} \\ {0,{{\rm{\;if\;}}}{t_i} < Now - {t_{{{\rm{thres}}}}}} \end{array}} \right.$ | (7) |
其中, Now表示当前时间; active@tthres表示该候选人在代码评审ri中添加评论的时间ti是否在时间范围tthres内, 时间范围tthres是方法的输入参数.
2.3 多目标优化方法前面提到, MOC2R方法需要优化3个目标.很显然, 同时在所有目标上达到最优是很困难的.MOC2R方法希望获得帕累托边界(Pareto front)[17]上的一组解(solution), 这组解能够支配其他解, 也就是说比其他解优越.
MOC2R使用NSGA-II算法(non-dominated sorting genetic algorithm-II)[18]优化前面提到的3个目标. NSGA-II是在软件工程和其他领域均被广泛使用的多目标优化方法[19-21].根据Harman等人的研究[22], 有超过65%的软件分析相关的优化技术是基于遗传算法(对于单目标优化)和NSGA-II(对于多目标优化).
在我们的评审人推荐场景中, 帕累托边界表示NSGA-II得到的在3个目标之间的最佳权衡.管理人员可以通过检查帕累托边界发现最合适的权衡解.
MOC2R的多目标优化方法包括以下4个步骤.
1) 表示.像其他选择问题一样[23-25], 我们将每个候选评审人编码为一个二进制变量.如果评审人被选中, 值为1;否则, 值为0.MOC2R得到的解是一个二进制变量的向量, 向量的长度是所有的候选评审人.评审人推荐问题的解空间是所有候选评审人是否被选中的组合.
2) 初始化.MOC2R随机产生初始种群, 也就是说, 在解空间中随机选择K个解.根据Harman[22]的建议, 我们将K设置为200.
3) 遗传算子.对于二进制编码的解的演化, 我们使用标准遗传算子[26].我们使用单点交叉、按位变异的方式产生下一代.我们使用二进制比赛方式进行选择操作, 也就是说, 随机选择两个解进行交叉和变异, 然后选择适应性最强的两个解进入下一代.
4) 适应性函数.由于我们希望优化3个目标, 每个候选解都用第2.2节描述的3个目标函数进行衡量.对于每个目标, 我们首先得到每个解中评审人的目标值, 然后将该解中所有选中人员的目标值求和.
3 实验设计 3.1 研究问题我们通过以下3个问题, 从方法的性能、各个目标的作用、参数的影响这3个方面验证方法的效果.
● RQ1:MOC2R方法在评审人推荐方面的效果如何?
● RQ2:MOC2R方法的3个优化目标对于评审人推荐的贡献是怎样的?
● RQ3:MOC2R在不同参数下的敏感度如何?
本方法主要希望推荐可以快速响应的合适评审人, 一个工作日内反馈对开发者和项目管理者都是非常有益的[15], 所以对于方法中的响应时间窗φ, 我们分别取2h、4h、8h进行实验, 并给出对比结果和分析.
3.2 GroundTruth和基线方法响应时间约束的代码评审人推荐的GroundTruth是基于历史代码评审活动中评审人的参与记录得到的.具体来说: 我们首先获取测试集中每个代码评审实际参与的评审人, 并计算他们留下第1条评论的时间与该代码评审创建时间之间的间隔.此时间间隔即为该评审人在本次评审中的响应时间.
本次实验中, 我们选择了ReviewFinder[5]和IR+CN[10]两种代码评审人推荐算法作为基线.这两种算法均是业内领先的代码评审人推荐算法, 并被很多研究所引用.
ReviewFinder的主要思想是: 假设大多数大型项目中, 目录结构组织良好, 具有相似文件路径的文件实现的功能是相似的或紧密关联的.该方法通过计算文件相似度获得两次代码评审的相似度得分, 对于一个新的代码评审任务, 计算每个历史评审的相似度得分, 并将得分分配给参与过相应历史评审的候选人, 候选人中按累积分数高低推荐给新的代码评审任务.
IR+CN是一个结合了信息检索和社交网络的混合推荐方法, 一方面, 该方法从历史评论记录中提取每一位候选评审人的兴趣信息, 对于一个新的代码评审, 与这个代码评审发起者具有相同兴趣的评审人被认为是合适的代码评审人; 同时, 结合信息检索算法对两个合并请求的相似度进行比较, 得到最终的推荐结果.
3.3 实验数据采集和预处理为了采集实验数据, 我们在GitHub中综合考虑Star个数和合并请求个数, 选择了6个开源项目, 包括facebook/react、tensorflow/tensorflow、twbs/bootstrap、ohmyzsh/ohmyzsh、flutter/flutter和electron/electron.这6个开源项目已关闭的合并请求个数均在5 000以上, 平均每个项目获得了5K+的Watch、114.35K+的Star和35.7K+的Fork.其中, Watch表示关注, 只要项目发生变动, 关注的人都会收到通知消息; Star表示点赞, 表示对项目的支持和喜欢; Fork表示创建项目代码库的分支, 并拷贝到自己账号中.3个指标从不同角度反映了项目的受欢迎程度, 值越大, 说明项目越受欢迎.此外, 这些开源项目中的每一个都得到了广泛的应用, 并在各自的技术领域发挥着重要的作用.我们通过GitHub REST API v3(https://developer.github.com/v3/)抓取这6个开源项目的相关数据.采集完成后数据信息见表 3.
![]() |
Table 3 Data set 表 3 数据集 |
在本实验中, 对收集到的合并请求进行了如下过滤.
a) 去掉了少于两个评审人员参与的合并请求.因为当一次代码评审过程中评审人数大于2次时, 这次代码评审才是可信的[27, 28].
b) 按基线算法IR+CN[10]的数据要求, 对合并请求中标题和描述信息进行了去除停留词和词干还原, 并将标题和描述信息中单词总数少于5个词的合并请求去掉.
和已有评审推荐方法[5, 12]的实验设置类似, 我们取各项目中最新的1 000个合并请求作为测试集, 其他合并请求作为训练集.
对于方法中的活跃性时间范围参数tthres, 我们在训练集上采用十折交叉验证的方式, 分别评估tthres为1d、3d、7d、15d、30d的推荐效果, 结果发现, tthres为3d时, 各个项目均能取得较好的效果.因此, 时间范围参数tthres设置为3d.
3.4 评价指标为了评估我们的方法, 我们使用时间窗约束的Top-k准确率和时间窗约束的平均倒数排名(mean reciprocal rank, 简称MRR)这两个度量指标.这两个度量指标经常被应用于软件工程领域推荐系统的评估工作中[6, 22, 29].
1) 时间窗约束的Top-k准确率计算的是方法推荐的Top-k个评审人, 至少一人在约定时间内出现在实际评审人列表中的合并请求的个数和合并请求总个数的百分比.给出一系列能够在响应时间阈值φ内响应的合并请求(PR@φ), 时间窗约束的Top-k准确率可以根据公式(8)进行计算:
$ 时间窗口约束的{\rm{Top-}}k准确率=\frac{{\displaystyle {\sum }_{pr\in PR@\phi }isCorrect(pr@\phi ,{\rm{Top-}}k)}}{|PR@\phi |}\times 100\%$ | (8) |
$ isCorrect(pr@\phi ,{\rm{Top-}}k)=\{\begin{array}{l}1,{\rm{\;\;if\;}}推荐k个评审人中至少一人在约定时间\phi 内进行响应 \\ 0,{\rm{\;if\;}}推荐k个评审人中没有人在约定时间\phi 内进行响应 \end{array}$ | (9) |
其中, isCorrect(pr@φ, Top-k)函数在至少有一个Top-k中的评审人员参与了该合并请求的代码评审, 且其最快响应时间小于φ的情况下返回1;否则, 返回0;
2) 时间窗约束的MRR计算的是代码评审人推荐列表中正确推荐的评审人倒数排名的平均值.给出一系列能够在响应时间窗φ内响应的合并请求(PR@φ), MRR可以根据如下公式进行计算:
$MRR = \frac{1}{{|PR@\varphi |}}\sum\limits_{pr \in PR@\varphi } {\frac{1}{{rank(Reviewers(pr))}}} $ | (10) |
其中, rank(Reviewers(pr))返回推荐列表中第1个实际参与了该合并请求的评审人的排名.当推荐列表中的评审人没有任何一个参与了该合并请求的实际评审时, 返回0.
理想情况下, 一个方法能够完美推荐代码评审人时, MRR值为1.
4 结果分析 4.1 RQ1:方法性能表 4和表 5分别列出了MOC2R以及基线方法在6个实验项目上在不同时间窗约束下的Top-k准确率和MRR结果.
![]() |
Table 4 Result of Top-k accuracy in different constrained time window (%) 表 4 不同时间窗约束的Top-k准确率结果 (%) |
![]() |
Table 5 Result of MRR in different time window constrained 表 5 不同时间窗约束的MRR结果 |
由表 4和表 5可以看出, 在不同的时间窗约束下, MOC2R都能得到较好的效果: Top-1准确率为41.7%~ 61.5%, Top-3准确率为58.4%~74.9%, Top-5准确率为66.5%~77.7%, MRR为0.53~0.58;平均Top-1准确率为51%, 平均Top-3准确率为66.6%, 平均Top-5准确率为72.1%, 平均MRR为0.61.这说明MOC2R可以很好地在多目标优化中推荐在时间约束下(约定时间窗内响应)最合适的评审人.准确率随着时间窗加大而增加的项目, 是由于其评审人的响应速度较慢, 倾向于在较长的时间中响应; 而准确率随着时间窗加大而减少的项目, 是由于该项目的评审人的响应速度较快, 倾向于在较短的时间内响应.
我们可以看到, 相对于ReviewFinder和IR+CN这两种推荐方法, 时间窗约束越强的窗口, MOC2R方法的优势越明显.当时间窗约束为2h时:
● 与ReviewFinder方法相比, MOC2R方法的Top-1准确率比ReviewFinder平均提高了143%((51%-21%)/21%), MOC2R方法的Top-5准确率平均提高了63%((72.1%-44.3%)/44.3%), MRR平均提高了97% ((0.61-0.31)/0.31).
● 与IR+CN方法相比, MOC2R方法的Top-1准确率平均提高了81%((51%-28.2%)/28.2%), Top-5准确率平均提高了35%((72.1%-53.3%)/53.3%), MRR提升了56%((0.61-0.39)/0.39).
并且, IR+CN方法在推荐效果上优于ReviewFinder方法.这是因为IR+CN在考虑两次代码评审的相似度基础上, 还通过社交网络方式考虑了两个评审人的相似度.
进一步地, 在整体响应时间较慢的项目(例如ohmyzsh/ohmyzsh), 我们方法的MRR指标能够2倍以上((0.61-0.28)/0.28)优于基线算法.这说明, 我们方法推荐的第1个正确的评审人的排序位置更靠前.
4.2 RQ2:各个目标的贡献为了清晰地比较各个目标对评审人推荐性能的影响, 我们对MOC2R的3个目标分别进行了实验分析.我们将EXP(ExpertiseScore)、RSP(ResponseScore)和ACT(ActivScore)分别以单目标方式和双目标方式进行评审人推荐: 对于单目标方式, 我们按照该目标的值进行排序; 对于双目标方式, 我们基于两个目标运行多目标优化算法.图 6~图 8分别列出不同组合方式在不同时间窗约束下的Top-k准确率和MRR.
![]() |
Fig. 6 Top-k accuracy & MRR in different objective, time window constrained φ=2h 图 6 时间窗约束φ为2h, 各目标Top-k准确率和MRR |
![]() |
Fig. 7 Top-k Accuracy & MRR in different objective, time window constrained φ=4h 图 7 时间窗约束φ为4h, 各目标Top-k准确率和MRR |
![]() |
Fig. 8 Top-k Accuracy & MRR in different objective, time window constrained φ=8h 图 8 时间窗约束φ为8h, 各目标Top-k准确率和MRR |
从图中可以看出, 在时间窗约束为2h时, 单个目标的Top-1准确率平均为21%~40%, MRR平均为0.31~ 0.49;使用两个目标的Top-1准确率平均为44%~49%, MRR平均为0.48~0.57;而MOC2R方法的平均Top-1准确率为51%, MRR为0.61, 高于单目标和双目标的情况.这说明, MOC2R方法中运用的经验、响应概率、活跃性这3个目标缺一不可, 共同对于评审人推荐发挥作用.
对于采用两个目标的情况, 我们看到, 去掉约定时间内的响应概率目标, 评审人推荐效果最差, 这说明该目标对于考虑响应时间的评审人推荐的贡献最大; 并且随着时间窗约束的增大, 评审人推荐效果下降的幅度逐渐缩小, 表明对于评审人推荐的贡献变小.这很好理解: 时间窗约束得越严格, 越要求评审人的响应时间足够快, 而评审人约定时间内的响应概率, 就是评审人该方面的度量.
对于采用单个目标, 我们可以看到, 只采用人员经验的评审人推荐效果最低.这意味着仅仅考虑评审人员经验是不够的, 有经验的人员如果不能及时响应评审任务, 无疑会对项目和社区代码贡献者产生负面影响.这也说明考虑响应时间的评审人推荐的重要性.基于响应概率或活跃性指标得到的推荐效果优于基于人员经验的推荐效果, 这说明在考虑响应时间的评审人推荐问题中, 人员过去活动这方面的信息是需要纳入考虑的重要因素.
4.3 RQ3:方法的敏感性活跃性指标中的时间范围tthres是MOC2R方法的参数, 为了分析其对于算法的影响, 我们对时间范围设定了一系列实验值tthres={1d, 3d, 7d, 15d, 30d}, 并对MOC2R在不同参数的性能进行了分析.表 6列出了时间窗约束为4h的Top-3准确率, 在其他时间窗下的准确率趋势相似.
![]() |
Table 6 Top-3 accuracy of MOC2R in different time limits tthres (time window constrained φ=4h) (%) 表 6 时间窗约束φ为4h, 在不同时间范围tthres中, MOC2R Top-3准确率(%) |
除ohmyzsh/ohmyzsh项目外, 在tthres取值1d或3d时, MOC2R的Top-3准确率能得到对比实验中的最大值, tthres取值7d、15d和30d时, Top-3准确率小幅下降, 降幅小于5%.我们认为, 一般来说, 当tthres设置较大值时, 能够潜在地将更多可能的人员包含进来, 但同时也引入噪声, 可能会影响推荐效果; 而当tthres设置较小值时, 能够过滤掉噪声对于推荐效果的影响, 得到较好的推荐效果.对于6个项目中贡献者活跃性最小的ohmyzsh/ ohmyzsh, 较长时间的活跃性时间范围tthres反而能够更加准确地帮助我们推荐合适的代码评审人.
5 讨论特定算法的性能因项目而异.如表 3和表 4所示, MOC2R在不同的项目中具有不同的Top-k准确度和不同的MRR表现, 其他算法也是如此.我们仔细地分析了6个开源项目的数据和其在GitHub上的组织管理方式, 除平均响应时间最慢的ohmyzsh/ohmyzsh项目外, 其他5个开源项目均配置了Facebook的机器人Robot (https://github.com/facebookarchive/mention-bot), 项目中所有的合并请求都会在第一时间被Robot进行统一处理, 分配一个或多个标签进行分类, 比如缺陷、改进、新特性、新版本等标签.并且在执行了自动化测试和静态检查的项目中, Robot还会根据自动化测试与静态检查结果判断是否提醒核心开发人员关注该合并请求状态.在此基础上, 我们对flutter/flutter项目进行了统计.该项目未使用Robot预处理合并请求之前, 其合并请求的平均最快响应时间约为7.5h;而在使用了Robot之后, 最近一年的合并请求的平均最快响应时间保持在4h以内.Robot的使用, 可以帮助贡献者和核心开发人员更好地理解合并请求, 并帮助他们选择要查看的合并请求, 缩短了响应时间.但现有的Robot背后的机制是基于贡献者提交的变更代码行寻找潜在的评审人, 如果Robot可以使用本文提出的MOC2R方法自动为合并请求推荐评审人, 那么对提升代码评审效率、提高开源社区的活跃性将会起到很好的促进作用.
另一方面, 代码评审人推荐准确率越高, 并不代表推荐的评审人越能够找到更多的问题.针对代码评审质量的判别方法、判断依据的相关研究还比较少.因为我们进行代码评审的直接目的还是希望能够进一步提升软件产品的质量, 那么如何评估一次代码评审做的好不好、什么样的代码评审人在评审过程中能够发现更多的问题, 也将会成为我们下一个阶段的研究方向.
6 相关工作近年来, 国内外出现了许多关于代码评审人推荐的研究和算法.根据它们考虑的主要特征和用于推荐代码评审人的主要技术, 我们将其分为4组: i) 启发式方法; ii) 基于机器学习的方法; iii) 基于社交网络的方法; iv) 混合方法.
6.1 启发式方法传统的推荐方法分析以往的提交和评审信息, 如文件修改历史记录、文件路径历史信息、代码行修改历史、历史评审中评审人评论次数等, 并基于评审人的修改经验或评审经验来寻找最相关的代码评审人员.主要的算法有ReviewBot、RevFinder、WRC和CORRECT等.ReviewBot是Balachandrany于2013年提出并实现的一款工具[6], 被广泛认为是最早的代码评审人推荐研究之一.其推荐依据是基于如下假设: 在合并请求中更改的代码行, 应该由先前讨论或修改过相同代码行的代码评审人来评审.Thongtanunam等人于2015年提出了ReviewFinder[5], 也是目前被广泛引用的推荐算法.该方法采用的是合并请求中包含的文件路径相似度的计算与排序的方法FPS(file path similarity).Hannebauer等人于2016年提出了FPS的优化算法WRC[7].该方法在FPS的基础上增加了前置步骤, 通过加权评论数的方式将评审经验引入FPS的计算过程中, 以便得到更精确的推荐结果.Rahman等人于2016年提出了代码评审人推荐算法CORRECT[16], 使用过相似技术或引用过相似的代码库的评审人是合适的候补代码评审人.
6.2 基于机器学习和信息检索的方法这组方法使用不同的机器学习算法或者信息检索方法来推荐代码评审人员, 它们不同于前一组的主要区别在于, 它们首先需要建立一个基于训练集的模型.“Pred.Rev.”是Jeoung等人于2009年提出来的[8], 基于补丁元数据、补丁内容和bug报告信息等一系列特征, 利用贝叶斯网络预测代码评审人员和补丁接受度的方法.同样使用朴素贝叶斯算法预测评审人的还有Lipcak[9]和Jiang等人[30, 31].Lu等人于2016年提出了基于时间和影响力因子的信息检索评审人推荐算法[32].
6.3 基于社交网络的方法这组方法中, 社交网络被用来确定开发人员之间评审交流的相似性, 这就为代码评审人员的推荐提供了更多相似的候选对象.CN(comment network)方法是Yu等人通过分析贡献者和开发者之间的社会关系提出的一种代码评审人推荐方法[10], 其假设开发者的兴趣可以从他们的评论中提取出来, 与合并请求的发起者共享共同兴趣的开发人员被认为是合适的代码评审人员.
6.4 混合方法其他一些研究中, 研究人员采用了不同的方法进行混合来推荐代码评审人员, 例如CoreDevRec、TIE、IR+ CN、PR+CF等[10-13].
以上方法的评价指标均为能够推荐合适的代码评审人, 而第1.1节的数据分析表明, 在开源社区的代码评审实践中, 存在很多的合并请求不能及时得到响应的情况, 这延长了评审周期、降低了参与人员的积极性和项目的发展.上述提到的基于准确性的代码评审人推荐方法并不能解决响应时间的问题, 因此, 我们提出了响应时间约束的代码评审人推荐问题和基于多目标优化的代码评审人推荐方法, 能够推荐合适且响应速度快的评审人, 提高代码评审的响应速度和社区活跃性.
7 结论本文提出了响应时间约束的代码评审人推荐问题和基于多目标优化的代码评审人推荐算法MOC2R, 通过最大化代码评审人员的经验、最大化推荐人员在约定时间内的响应概率、最大化人员的活跃性来为代码评审推荐人员.实验结果表明, MOC2R能够取得很好的推荐效果.在未来, 我们计划探索更多的优化目标, 有助于选择更加合适的代码评审人.同时寻求机会企业内部部署MOC2R, 以便更好地评估它在实践中的表现.还将研究如何评估代码评审质量, 以便进一步优化评审人推荐方法.
[1] |
Bacchelli A, Bird C. Expectations, outcomes, and challenges of modern code review. In: Proc. of the 2013 Int'l Conf. on Software Engineering. IEEE, 2013. 712-721.
|
[2] |
Gousios G, Pinzger M, van Deursen A. An exploratory study of the pull-based software development model. In: Proc. of the 36th Int'l Conf. on Software Engineering. ACM, 2014. 345-355.
|
[3] |
Gousios G, Zaidman A, Storey MA, Van Deursen A. Work practices and challenges in pull-based development: The integrator's perspective. In: Proc. of the 37th Int'l Conf. on Software Engineering, Vol. 1. IEEE, 2015. 358-368.
|
[4] |
Gousios G, Storey MA, Bacchelli A. Work practices and challenges in pull-based development: The contributor's perspective. In: Proc. of the ICSE 2016. 285-296.
|
[5] |
Thongtanunam P, Tantithamthavorn C, Kula RG, Yoshida N, Iida H, Matsumoto KI. Who should review my code? A file location-based code-reviewer recommendation approach for modern code review. In: Proc. of the 2015 IEEE 22nd Int'l Conf. on Software Analysis, Evolutionand Reengineering (SANER). IEEE, 2015. 141-150.
|
[6] |
Balachandran V. Reducing human effort and improving quality in peer code reviews using automatic static analysis and reviewer recommendation. In: Proc. of the ICSE 2013. 2013. 931-940.
|
[7] |
Hannebauer C. Automatically recommending code reviewers based on their expertise: An empirical comparison. In: Proc. of the ASE 2016. 2016. 99-110.
|
[8] |
Jeong G, Kim S, Zimmermann T, Yi K. Improving code review by predicting reviewers and acceptance of patches. In: Proc. of the Research on Software Analysis for Error-free Computing Center Tech-Memo (ROSAEC MEMO 2009). 2009. 1-18.
|
[9] |
Lipcak J, Rossi B. A large-scale study on source code reviewer recommendation. In: Proc. of the 201844th Euromicro Conf. on Software Engineering and Advanced Applications (SEAA). IEEE, 2018. [doi: 10.1109/SEAA.2018.00068]
|
[10] |
Yu Y, Wang H, Yin G, Wang T. Reviewer recommendation for pull-requests in Github: What can we learn from code review and bug assignment?. Information and Software Technology, 2016, 74: 204-218.
[doi:10.1016/j.infsof.2016.01.004] |
[11] |
Jiang J, He JH, Chen XY. CoreDevRec: Automatic core member recommendation for contribution evaluation. Journal of Computer Science and Technology, 2015, 30(5): 998-1016.
[doi:10.1007/s11390-015-1577-3] |
[12] |
Xia X, Lo D, Wang X, Yang X. Who should review this change? Putting text and file location analyses together for more accurate recommendations. In: Proc. of the 2015 IEEE Int'l Conf. on Software Maintenance and Evolution (ICSME). IEEE, 2015. 261-270.
|
[13] |
Xia Z, Sun H, Jiang J, Wang X, Liu X. A hybrid approach to code reviewer recommendation with collaborative filtering. In: Proc. of the 20176th Int'l Workshop on Software Mining (Software Mining). IEEE, 2017. 24-31.
|
[14] |
Yang C, Zhang X, Zeng L, Fan Q, Yin G, Wang H. An empirical study of reviewer recommendation in pull-based development model. In: Proc. of the 9th Asia-Pacific Symp. on Internetware. ACM, 2017. Article No. 14.
|
[15] | |
[16] |
Rahman MM, Roy CK, Collins JA. Correct: Code reviewer recommendation in Github based on cross-project and technology experience. In: Proc. of the IEEE/ACM Int'l Conf. on Software Engineering Companion (ICSE-C). IEEE, 2016. 222-231.
|
[17] |
Teich J. Pareto-front exploration with uncertain objectives. In: Proc. of the EMO 2001. 2001. 314-328.
|
[18] |
Deb K, Agrawal S, Pratap A, Meyarivan T. A fast elitist non-dominated sorting genetic algorithm for multi-objective optimization: NSGA-II. In: Proc. of the PPSN 2000. 2000. 849-858.
|
[19] |
Mondal D, Hemmati H, Durocher S. Exploring test suite diversification and code coverage in multi-objective test case selection. In: Proc. of the ICST 2015. 2015. 1-10.
|
[20] |
Yoo S, Harman M. Pareto efficient multi-objective test case selection. In: Proc. of the ISSTA 2007. 2007. 140-150.
|
[21] |
Tantithamthavorn C, Teekavanich R, Ihara A, Matsumoto KI. Mining a change history to quickly identify bug locations: A case study of the eclipse project. In: Proc. of the ISSREW 2013. 2013. 108-113.
|
[22] |
Harman M, Mansouri SA, Zhang Y. Search-based software engineering: Trends, techniques and applications. ACM Computing Surveys (CSUR), 2012, 45(1): Article No. 11.
|
[23] |
Epitropakis MG, Yoo S, Harman M, Burke EK. Empirical evaluation of Pareto efficient multi-objective regression test case prioritisation. In: Proc. of the ISSTA 2015. 2015. 234-245.
|
[24] |
Silva RA, de Souza SDRS, de Souza PSL. A systematic review on search-based mutation testing. Information and Software Technology, 2017, 81: 19-35.
[doi:10.1016/j.infsof.2016.01.017] |
[25] |
Jeong G, Kim S, Zimmermann T. Improving bug triage with bug tossing graphs. In: Proc. of the FSE 2009. 2009. 111-120.
|
[26] |
Langdon WB, Harman M, Jia Y. Efficient multi-objective higher order mutation testing with genetic programming. The Journal of Systems and Software, 2010, 83(12): 2416-2430.
[doi:10.1016/j.jss.2010.07.027] |
[27] |
Rigby PC, German DM, Cowen L, Storey MA. Peer review on open-source software projects: Parameters, statistical models, and theory. ACM Trans. on Software Engineering and Methodology (TOSEM), 2014, 23(4).
|
[28] |
Sauer C, Jeffery DR, Land L, Yetton P. The effectiveness of software development technical reviews: A behaviorally motivated program of research. IEEE Trans. on Software Engineering, 2000, 26(1): 1-14.
[doi:10.1109/32.825763] |
[29] |
Tantithamthavorn C, Ihara A, Matsumoto KI. Using co-change histories to improve bug localization performance. In: Proc. of the SNPD 2013. 2013. 543-548.
|
[30] |
Jiang J, Yang Y, He J, Blanc X, Zhang L. Who should comment on this pull request? Analyzing attributes for more accurate commenter recommendation in pull-based development. Information and Software Technology, 2017, 84: 48-62.
[doi:10.1016/j.infsof.2016.10.006] |
[31] |
Jiang J, David L, Zhang L. Who should make decision on this pull request? Analyzing time-decaying relationships and file similarities for integrator prediction. The Journal of Systems and Software, 2019, 154: 196-210.
[doi:10.1016/j.jss.2019.04.055] |
[32] |
Lu S, Yang D, Hu J, Zhang X. Code reviewer recommendation based on time and impact factor for pull request in Github. Computer Systems & Applications, 2016, 25(12): 155-161(in Chinese with English abstract).
https://www.cnki.com.cn/Article/CJFDTOTAL-XTYY201612024.htm |
[32] |
卢松, 杨达, 胡军, 张潇. 基于时间和影响力因子的Github Pull Request评审人推荐. 计算机系统应用, 2016, 25(12): 155-161.
https://www.cnki.com.cn/Article/CJFDTOTAL-XTYY201612024.htm |