張小鵬,趙逢禹,劉 亞
(上海理工大學 光電信息與計算機工程學院,上海 200093)
在大型軟件項目設計開發過程中,代碼評審(Code Review)是發現代碼缺陷進而提高軟件質量的重要手段.Bavota等人[1]通過對三個開源系統的探索性研究,旨在調查代碼評審對代碼缺陷修復和提交代碼組件質量的影響.他們的研究表明手動評審代碼對軟件項目的代碼質量有著重大的影響.QT、Android和Open Stack軟件項目為了維護項目的代碼質量,更是保持了一個龐大的代碼評審團隊[2].由此可見代碼評審確實能夠更好的保障軟件項目的質量.
目前關于代碼評審的研究主要集中在代碼評審時的責任分配[3,4]、對軟件項目質量的影響[1,2,5]、評審方法研究[6]和自動的推薦代碼評審者等方面.Weiss[7]等人研究發現,針對開源軟件項目中的代碼提交,具有評審者分配問題的代碼提交時間相比沒有分配問題的提交時間平均會多花費6到12天.更重要的是,有些提交的代碼從未收到任何代碼評審意見,也就無法被合并到主代碼庫.由此可以看出,如何為代碼找到合適的評審者對保障軟件系統的質量、提高軟件的開發效率是非常有價值的.
在早期的代碼評審推薦研究中,McDonald和Ackerman改進了基礎的Line 10 Rule評審者推薦算法,使用了三種數據來標識評審者[8].該算法首先要求所有的評審者都要創建自己的概要文件;然后使用提交日志信息統計每個評審者評審過的模塊總數;最后從問題跟蹤器中為具有代表性的問題描述建立索引.利用這些數據,可以根據新提交問題的描述進行評審者的推薦.
Balachandran提出了基于修改歷史的評審者推薦算法Review Bot[9].它利用代碼層次的修改歷史來推薦評審者.如果一次新提交所涉及的修改代碼擁有修改歷史,Review Bot將會為候選的評審者計算相應修改代碼的修改次數.
Thongtanunam等人提出了利用文件路徑相似性推薦代碼評審者的FPS(File Path Similarity)算法[10].該算法假設大多數大型軟件項目的目錄結構是規范的和組織良好的,文件路徑與其功能是密切相關的.算法利用候選評審者的歷史評審文件路徑和新提交代碼涉及到的文件路徑的相似性來推薦評審者.在其隨后的研究[11]中進一步使用了更加復雜的路徑相似性算法,比較兩條路徑的最長公共前綴、子序列等其他信息,并且添加了新的開源項目(Libre Office)來檢驗其效果.
Jiang等人利用開發者與評審者之間的社會關系屬性來推薦代碼評審者[12].他們研究發現使用機器學習中的Support Vector Machines方法可以得到最好的推薦表現.但是因為他們的算法使用的實驗數據無法從其他軟件項目的公開數據中獲取,所以他們的研究結果沒有重復性和可比性.
上述評審者推薦方法大都沒有考慮到評審數據的時間效力和細粒度的評審內容.評審的時間性能夠反映出評審者當前的評審重心,所以越是近期的評審越重要,在進行推薦時需要為當前的評審賦予更高的時間效力,讓其發揮更大的作用.Thongtanunam等人使用了文件路徑來區分源代碼的功能,從而計算相似性,但這是一種粗粒度方法,無法詳盡的反映評審者的具體評審內容,所以需要一種更細粒度化的標準來判別評審者的具體工作內容,這樣就能夠得到更準確的內容相似性.
針對以上問題,本文提出了效力優化的代碼評審者推薦模型OCRRM(optimized code reviewer recommendation model).OCRRM模型首先根據評審的發生時間調整本次評審的時間效力,為最近的評審賦予更高的時間效力,然后將候選評審者的歷史評審信息提取為細粒度的更具體的能夠詳細反映評審者具體評審內容的信息,將提交代碼信息和候選評審者的歷史評審詳細信息的相似性作為內容效力,最后利用候選評審者的每次歷史評審的時間效力作為內容效力的權重來綜合推薦合適的代碼評審者.效力優化主要是利用時間效力調整內容效力的權重,既能夠利用詳細的具體的評審內容,又能夠讓近期的歷史評審發揮更大的作用,所以可以能夠有效推薦合適的代碼評審者.
評審者的歷史評審數據主要分為兩部分:評審者R的個人信息、評審者R的歷史評審信息集合.R的歷史評審數據可以表示為HRD(R)=
R.Reviews = {
其中Owneri、Datei、RCodei和Commentsi分別表示R的第i次歷史評審的代碼提交者、提交時間、評審的代碼信息和評審流程中的所有評論.RCodei是通過分析修改的源代碼得到的文件名、方法名的信息集合,可以表示為:
RCodei=
不同時期的歷史評審活動對評審者的時間貢獻效力是不同的,近期的評審數據更能夠反映出評審者近期的評審重點.而且即使是同一個源代碼文件,不同的評審者的評審內容和評審貢獻也是不同的.因而本文利用歷史評審數據的時間效力和內容效力對代碼評審者推薦模型進行優化,利用時間效力和內容效力來聯合推薦合適的代碼評審者.圖1給出了OCRRM的活動處理流程.
圖1中的OCRRM模型主要包含六個步驟:
1)獲取歷史評審信息
為了內容效力的計算,需要首先獲取所有的歷史評審信息.利用網絡爬蟲從數據來源網站上獲取歷史評審的源數據,然后將源數據分析整理為統一的HRD(R)格式,得到格式化的歷史評審數據集合,即HRD集合;

圖1 OCRRM模型流程圖
2)信息提取
利用文本提取從系統提交日志中提取出提交代碼的提交者信息,然后使用AST技術對源代碼中被修改的部分進一步分析,提取被修改代碼涉及到的類、方法等詳細內容;
3)獲取候選評審者集合
如果某個文件被某個評審者評審過,那么當它被再次修改時,就應該尋找曾經評審過該文件的評審者作為候選評審者.如果新提交代碼涉及到的文件都沒有評審歷史,那么全體評審者都是其候選評審者.如果涉及到的文件擁有評審歷史,那么就應該在HRD集合中尋找曾經評審過該文件的評審者,并將該評審者加入候選評審者集合;
4)內容效力計算
內容效力CE度量候選評審者歷史評審內容和新提交代碼內容的相似度,內容越相似,內容效力越大.候選評審者的每次歷史評審數據都會涉及到不同的源代碼修改,使用AST技術將每次源代碼中修改部分提取為更具體的內容,例如文件名、類名、方法名信息,可以反映出評審者的主要審核內容.然后利用改進的Jaccard相似度計算候選評審者的歷史評審內容和提交代碼內容的相似度,即內容效力得分;
5)時間效力計算
時間效力TE度量候選評審者某次歷史評審發生時間和與當前時間的時間間隔,間隔越小,時間效力越大.若候選評審者R的某次評審發生于t天之前,則這次評審的時間效力為1/(t+1),t>=0;
6)綜合推薦評審者
取得每個候選評審者的每次歷史評審的時間效力和內容效力后,就可以綜合兩部分來推薦合適的評審者.為了防止越推薦越集中,越集中越推薦的情況,本文認為只有內容效力不為0的歷史評審才是具有效力的歷史評審,候選評審者的推薦得分是由所有具有效力的歷史評審的時間效力和內容效力的乘積的和累加后除以有效評審次數得到的平均值,計算方法如公式(1)、公式(2)所示:
(1)
(2)
公式(1)、公式(2)中n表示候選的評審者R總的歷史評審次數,CEi表示第i次歷史評審的內容效力,TEi表示第i次歷史評審的時間效力,C表示在n次歷史評審中具有效力的評審次數,即CEi大于0的評審次數.這樣求得的推薦平均值就能夠剔除那些完全和新提交代碼無關的評審的影響,也能夠削弱評審者因為差異巨大的評審次數造成的影響.
計算出每個候選評審者的推薦得分后,根據推薦得分對候選評審者排序,然后就可以推薦前K名評審者.
在OCRRM模型中關鍵的技術主要有獲取歷史評審信息、候選評審者集合的獲取、歷史評審的時間效力和內容效力的計算.
本文選取了三個網站的評審數據進行分析,它們分別為QT、Android和Open Stack.這三個網站都可以獲取JSON格式的評審數據,并且數據格式是相似的,這為數據的獲取提供了極大的便利.以QT項目為例,一次完整的評審數據主要包括評審代碼的提交信息、評審者、版本數、不同版本涉及到的源代碼和評審者對不同版本代碼的評論.利用網絡爬蟲從來源網站上獲取存在于detailjson、detailServicejson和patchesjson中的源數據,通過解析json數據,從detailjson中獲取評審涉及到的提交者、評審者、提交日志信息,從detailServicejson中獲取所有的提交源文件、版本數、評審評論等信息,從patchesjson中獲取某一版本涉及到的修改源文件、提交信息,最后將解析結果存入本地數據庫.獲取所有的解析數據后,將其再次處理格式化為HRD格式的數據存入數據庫.這樣所有的數據就獲取處理完成,需要的時候只要訪問本地數據庫即可.
為了推薦合適的代碼評審者,需要首先獲取候選的代碼評審者.如果一名提交者的提交代碼中的某個文件被某名評審者多次評審,那么當提交者再次提交該段代碼時,就應該找該名評審者來評審.
為了快速獲取候選的評審者集合,算法使用提交代碼信息NFiles、所有的歷史評審數據HRD集合作為輸入,輸出候選評審者集合Revs.NFiles包含新提交代碼中涉及到的所有文件名.程序遍歷HRD集合,從中取出每一條HRD(R)數據,然后遍歷HRD(R)數據中的R.Review集合.如果NFiles中的文件被R.Review評審過,即評審者某次評審的文件中包含新提交代碼中的任一文件,那么就將該條HRD(R)所屬的R.Profile加入輸出的評審者集合Revs.
獲取候選評審者偽算法如下:

輸入:代碼的提交者信息 NFiles=
候選評審者的歷史評審數據包含了評審者開始評審該項目到至今的所有評審數據,時間跨度可能很長.如果將所有時間跨度的評審數據的時間效力看作一樣的,則會出現讓一個長久沒有評審的評審者評審新提交代碼的情況.為了把代碼推薦給能夠及時反應的評審人員,需要使用效力優化函數對不同時間跨度的歷史評審數據的時間效力進行調整.對于某位候選評審者R,第i次歷史評審的時間效力計算如公式(3)如示:
(3)
公式(3)中DN(以天為時間度量單位)表示當前時間,DRCi代表R第i次歷史評審的發生時間.評審者R的歷史評審發生時間距當前時間越近,則t越小,時間效力越大,最大為1,最小趨近于0.為了防止除0,在分母上加1.
某段代碼可能會被修改和提交評審過多次,產生多個版本.本文將每次代碼的修改提交都看作一次評審,即對于每一版本的代碼修改都看作是一次評審,這樣就可以充分利用足夠細化的數據.但是通過對評審的評論分析發現,在評審的版本演進過程中,并不是所有的評審者都在評審過程中留下了評論,這就造成了某些評審者的評審意見為空.可是他們作為評審流程的一員,應該是做出了部分貢獻,理應擁有評審數據,所以本文將版本演進造成的多次評審中的第一版評審數據作為所有評審者的基本數據.以QT項目的153840號Project評審*https://codereview.qt-project.org/#/c/153840/為例,該Project共有四個版本,看作四次評審,Patch Set 1中修改的類和方法作為該次評審所有評審者的基本數據.通過評論發現,Patch Set 2的評審數據應該是Leena的,而Patch Set 3和Patch Set 4號的評審數據分別是屬于Marc和Olivier的.
在得到評審者的歷史評審內容和新提交代碼內容后,使用改進的Jaccard相似度計算方法可以計算出評審者每一次的評審代碼內容和新提交代碼內容的相似度,即每一次的評審內容效力.
Jaccard相似度[13]是用來度量兩個不同維數集合之間的相似程度,又稱之為狹義Jaccard相似度,兩個集合的狹義相似度等于兩個集合的交集比上兩個集合的并集.但是本文在以新提交代碼內容為基礎度量新提交代碼內容和歷史評審內容的相似度時,更應該著重注意歷史評審內容對新提交代碼內容的覆蓋程度,即提交代碼內容和歷史評審內容的共有元素個數越多,對新提交代碼內容的覆蓋程度越大,相似度越大.為此,本文提出了改進的Jaccard相似度,利用改進Jaccard相似度計算新提交代碼內容和歷史評審內容的相似性.設新提交代碼的類集合P共有i個元素,歷史評審數據的類集合R共有j個元素,則P和R的交集G共有k個元素,如公式(4)-公式(6)所示:
P={p0,p1,…,pi}
(4)
R={r0,r1,…,rj}
(5)
G=P∩R={g0,g1,…,gk}, 0≤k
≤Min(i,j)
(6)
以P和R為基礎計算改進Jaccard相似度,如公式(7)所示:
(7)
公式(7)中|P|表示集合P的模,即P中元素的個數,|P∩R|表示集合P與R交集的模.k/i越大,表示評審內容和新提交代碼內容的共有元素個數越大,即候選評審者評審內容和新提交代碼內容越相近.
通過AST技術對評審者的歷史評審源代碼進行分析,提取其中被修改的類名和方法名.若評審者R的第i次歷史評審的類名相似度為CJ,方法名相似度為MJ,則R的第i次歷史評審內容的內容效力CE計算方法如公式(8)如表示:
CE(R,i)=a*CJ+(1-a)*MJ
(8)
公式(8)中a表示類名相似度的權重,1-a表示方法名相似度的權重.
本文采用的數據來自三個網上公開的代碼評審項目,它們分別是QT*https://codereview.qt-project.org/、Android(AN)*https://android-review.googlesource.com和Open Stack(OP)*https://review.openstack.org/#/q/status:merged.每個項目開發時間均超過五年,評審流程已經非常地成熟穩定.三個項目的大部分評審數據都是公開的,均可以在網上獲取.從三個項目網站中分別獲取id連續的3萬條數據,QT項目中id取150000-180000、AN項目中id取350000-380000、OP項目中id取350000-380000萬.這些數據都是近期的,可以保證數據是有效的和穩定的.從預處理的數據中選取公開的并且已合并的數據進行統計,統計結果如表1所示:
從表2中可以看出,OP項目的開源評審次數是最多的,數據也是最豐富的,QT項目的評審次數和數據豐富程度次之,AN項目的最少.以QT項目為例,選取的數據時間從2016/02/22到2016/12/15,共有19504次公開的已合并的項目評審,在19504次項目評審中,共涉及到681位評審者和54687個文件,681位評審者共評審了代碼修改51119次,評審了文件116664次,評審了72555次不同版本的代碼修改.平均每次項目合并涉及到2.62次評審、5.98個文件和3.72個版本.

表1 實驗數據統計
本文主要通過Top-k準確率和推薦平均準確率來對實驗結果進行分析.對于公式(8)中的內容效力CE中a的取值,本文經過一部分實驗選取其最優取值為0.76.

表2 TOP-K準確率對比
Top-k準確率表示算法推薦的前k名評審者的準確率.K越小,Top-k越高,表示推薦算法的推薦效果越好.當Top-1準確率為1時,表示算法總能推薦想要的結果,這是最理想的情況.給定一個推薦的評審者集合Rc和實際的評審者結合Rr,如公式(9)、公式(10),則Top-k準確率計算方法如公式(11)如示:
RC={r0,r1…ri},i=0,1,…k
(9)
Rr={r0,r1…ri},j=0,1,…n
(10)
(11)
如果實際評審者Rr中的前k名評審者包含推薦的第i名評審者ri,則isContain()函數返回1,否則返回0.根據文獻[12],本文中選擇k值為1、3、5.例如,Rr={a,b,c,d,e},Rc={a,c,f,b,e,d},則Top-1、Top-3、Top-5準確率依次為100%、66.7%和80%.
OP、QT和AN項目的Top-k準確率如表2所示.表2中共包含了四種方法OCRRM、REVIEWBOT、Number of Changes和Expertise Recommender(ER)在三個項目上的TOP-K值[11].本文模型OCCRM在三個項目上的Top-5準確率達到了63%、54%和58%,而ER的TOP-5準確率只有51%、53%和54%.從表中可以看出,在QT項目上的TOP-K準確率兩者大致是相同的,而OP項目上的TOP-K準確率OCCRM模型更高.雖然在AN項目上的TOP-1和TOP-3是ER方法更好,但是TOP-5準確率仍是OCCRM方法更好,說明OCCRM模型能夠有效地提高推薦準確率,尤其是推薦人數較多的時候.
推薦平均準確率表示推薦的專家中實際參加了評審的專家的比例.在統計三個實驗項目的推薦平均準確率時,每進行10次評審者推薦統計一次推薦平均準確率.三個項目的推薦平均準確率如圖2所示.

圖2 OP、QT和AN的推薦平均準確率
從圖2中可以看出,三個項目的推薦平均準確率在訓練的初期因為數據的缺乏都很低.隨著數據的豐富,推薦平均準確率迅速上升,達到收斂后在收斂準確率附近變化.OP項目的訓練使用了約15%的評審數據,推薦平均準確率收斂后可以達到74.42%.QT項目的訓練使用了約22%的評審數據,推薦平均準確率收斂后為64.63%.AN項目的訓練使用了約34%的評審數據,推薦平均準確率收斂后為67.27%.而在文獻[11]中,Expertise Cloud方法在三個項目上的平均準確率約為65.3%、60.3%和59.6%,Expertise Recommender方法的平均準確率約為58.8%、55.9%和58.5%.由此可見本文的OCCRM模型可以達到較高的推薦平均準確率,證明本文的方法有效.
基于評審歷史的代碼評審者推薦方法是代碼評審的主要研究方向之一.本文提出的效力優化的代碼評審者推薦模型OCRRM考慮了不同時期發生的歷史評審數據對最終的推薦結果的影響,并且將歷史評審數據提取為能夠反映評審者評審具體內容和貢獻的內容.在三個大型開源軟件公開評審數據上的實驗證明本模型能夠有效的提高代碼評審者的推薦準確率.雖然本文的實驗數據很豐富,但是選取的數據都是三個項目中的連續的一部分,沒有從頭到尾的對一個項目完整的進行實驗,以驗證本模型在完整項目實驗數據上的有效性.因此在后續工作中將進一步優化程序和驗證完整的項目數據.