趙海燕,李 敏,陳慶奎,曹 健
1(上海市現代光學系統重點實驗室,光學儀器與系統教育部工程研究中心,上海理工大學光電信息與計算機工程學院,上海 200093)2(上海交通大學 計算機科學與技術系,上海 200030)
軟件代碼評審作為一項軟件開發中的有效方法已有35年的歷史[1,2].隨著軟件工程的發展,代碼評審已經被各個軟件開發組織廣泛采用,并被證明是軟件開發項目中質量保證的有效手段,成為開源和專有軟件項目中提倡的最佳實踐[3,4].
在代碼評審中,要求由獨立的開發人員檢查新的代碼或者代碼的更改,以在代碼集成到系統之前能夠識別和修復代碼中的缺陷.雖然傳統的代碼評審已經被證明可以提高軟件產品的整體質量[5-7],然而傳統代碼評審通常需要舉行面對面的會議,有時一位評審員評審之后還需交給下一位評審員評審,整個流程嚴格按照規定的制度執行,導致整個過程比較繁瑣、費時,一定程度上也阻礙了它在實踐中的應用[8,9].
現代代碼評審[10,11]作為一種非正式的、輕量級的(不需要面對面正式會議及文件收集工作)、基于工具的代碼評審方法,已經在專有軟件和開源軟件的開發中廣泛使用.相對于正式代碼評審,輕量級代碼評審所耗費的各種成本明顯下降,如果正確實施,它可以起到更加積極的效果[6,11].
開源軟件開發依賴于開發者的志愿參與,因此更適合采用輕量級代碼評審.例如,GitHub提供了一個在線審查機制,以確保來自貢獻者的代碼質量,該審查機制是GitHub基于Pull軟件開發模型[12-14]的重要組成部分:項目的貢獻者可以通過添加新特性或修復某些bug對源代碼進行改進,改進的代碼不能直接提交到項目存儲庫,而是以Pull 請求的形式提交給社區,此請求將受到整個社區的審查.每個用戶都可以是一個潛在的評審員,他根據代碼風格、新特性的必要性、代碼邏輯的正確性等對請求進行評估.最后,集成人員會綜合考慮所有評審者的意見做出決定.
在評審過程中,評審者必須綜合考慮各方面的因素對代碼進行嚴格的審查.對評審者來說,此過程需要充分去理解代碼并對此作出評論,所以代碼評審是一個耗費腦力乃至體力的工作,也是一個知識密集型的工作.因此,找到合適的評審人員對最終的評審效果具有極大的意義[5,15].然而,在數百名潛在的評審員中篩選合適的評審人員已成為現代代碼評審的一項挑戰.特別是在開源項目中找到積極、有能力還有相關背景的評審者更為困難.
由于代碼評審的價值,它是目前軟件工程領域的一個重要研究主題,在許多國際會議,例如ICSE、ICSME、SANER、ICSM、SIGSOFT上都有論文對此進行研討.一方面,研究者們探討了影響開源代碼評審質量的各種因素,另一方面,如何提高開源代碼評審質量特別是推薦合適的評審者也成為了重要的研究內容.本論文對此領域的研究進行了系統的總結,并對未來的研究方向進行了討論.
一方面,代碼評審作為開源軟件開發過程的一個重要部分,其目的是客觀、及時、獨立地評估代碼的質量.另一方面,對于貢獻者而言,補丁代碼能否被接受、代碼是不是在最短時間內被接受等都是非常關心的.
原則上,代碼評審是一個透明的過程,評審者進行獨立的評估,然而在實踐中,該過程受諸多因素的影響.因此,近年來,研究者人員基于對大型開源項目的實際數據進行了實證研究.本文對近年來研究者們分析的各種影響因素進行了總結,并分為與開發者相關的因素、與評審者相關的因素、與項目相關的因素,如表1所示.
表1 代碼評審的影響因素
Table 1 Influencing factors of code review

因素類別影響因素影 響參考文獻請求提交次數提交次數越少請求被接受幾率越大,對代碼評審結果有正面影響[16]補丁的大小提交較小的補丁,分析復雜度低,對代碼評審過程有正面影響[12,16,17][18,20,21][22]是否首次提交Pull請求初次提交請求被拒絕的幾率大,對代碼評審結果有負面影響[16,18]與開發者相關的因素開發者身份開發者是核心團隊成員,對評審結果有正面影響[16,17,18][22,23]開發者與評審者之間的關系關系密切,對代碼評審速度有正面影響[16,22,23]Pull請求的位置對某目錄文件操作次數多,該目錄下文件被接受的幾率增大,對代碼評審結果有正面影響[12,16]開發者的經驗經驗豐富的開發者對代碼評審結果有正面影響[14,17,19]與評審員相關的因素評審人的活躍度活躍的評審員對代碼評審響應時間有正面影響[17]評審隊列長度評審員需要處理評審的任務隊列越短,對代碼評審速度有正面影響[17]項目涉及的編程語言某些編程語言如C、TypeScript等對代碼評審有正面影響[14,18]文件優先級項目中的文件等級越高對代碼評審結果有正面影響[17,20]與項目屬性相關的因素軟件組件不同的軟件組件對代碼評審時間有一定的影響[17]組織Pull請求所屬的組織機構對代碼評審速度有一定的影響[17]應用領域項目所屬領域對代碼評審有一定影響[14]項目的熱度項目的熱度會對代碼評審有一定的影響[12,14]
在開源軟件開發過程中,開發者通過提交Pull 請求為項目做出貢獻.一些研究者使用各種算法包括關聯規則挖掘算法對代碼評審影響因素進行了梳理,揭示了代碼評審過程受多方面因素的影響[12-23].與開發者相關的因素如下:
2.1.1 請求提交次數因素
Pull請求提交次數會影響評審[16].開發者提交請求次數變多,導致分析的復雜度增加,會增加評審員的工作量,所以請求被接受的幾率變小.
2.1.2 補丁的大小因素
開發者提交更小的補丁對代碼評審有正面影響[12,16-18,20-22].較小的補丁只需要經過幾輪修訂,而較大的補丁需要做更多的工作才能成功的并入項目.當開發者對項目中的文件進行添加處理,會增加分析的復雜性,降低Pull請求接受的幾率;反之,刪除文件,會使得分析的復雜性降低,增大其接受的幾率.
2.1.3 是否首次提交Pull請求
開發者對Pull請求有過歷史提交記錄,導致各方面修改比較完善,則在提交新Pull請求時,該請求被接受的幾率增大[16,18].
2.1.4 開發者的身份
開發者身份對代碼評審過程有的一定影響[16-18,22,23].通過開發者的概要信息,可知開發者是否為項目核心團隊成員.如果是核心團隊成員,其提交的請求被接受的幾率增大.
2.1.5 開發者與評審者之間的關系
在實際項目中,開發者和評審者之間可能具有追隨關系,而這種關系會對代碼評審帶來正面影響[16,22,23].在這種關系下,當開發者提交Pull請求時,評審者愿意評審該請求的幾率會增大.其次,當開發者與評審者之間擁有共同的專業技能和興趣時,評審者會對該請求更感興趣而使評審意愿增大.最后,當開發者與評審者社會關系密切時,評審者也會更傾向于評審此請求.
2.1.6 Pull請求的位置
不同的開發者可能會修改不同的文件,開發者可能對項目下的某些文件操作多于其他文件.研究發現,Pull請求的位置會影響代碼評審過程[12,16].從評審人分配角度,某些開發者在近期時間內,反復對某些文件進行修改,從而增加了該開發者成為這類文件的評審者的機會.從評審機會的角度,軟件項目中同一目錄下的文件具有一定的相似性,因此當Pull請求對應的文件屬于相同目錄時,需要的評審者是類似的.同樣,目錄的不同導致合適的評審者有差別.
2.1.7 開發者的經驗
開發者經驗在代碼評審中扮演重要角色.由經驗豐富的活躍開發者提出的請求,修改的內容較完善,評審時間會更短,導致接受機會增加.
研究者通過對項目的實證研究,發現評審人的某些因素對代碼評審有影響:
2.2.1 評審人的活躍度
評審人員的活躍度對項目評審的時間有一定影響[17].較為活躍的評審人員更愿意花更多的時間和精力去參與評審,導致評審響應時間更短.
2.2.2 評審任務隊列長度
評審人需要審核的請求隊列的大小與評審響應時間存在直接聯系,待評審隊列越短,評審員的工作量越少,則相應的評審員的評審速度越快[17].
開發者及評審者的工作都在某項目下進行,因此項目的某些屬性對代碼評審有著重要影響.近年來研究者們從若干方面進行分析,總結出相關因素如下:
2.3.1 項目涉及的編程語言
拉赫曼的研究表明在某些編程語言中,請求被接受的幾率更大[14].實驗證明,使用Java、CSS、JavaScript和C++等語言編寫的請求被接受的幾率相對降低,而使用C#、 C、TypeScript、Scala和Go等會增大Pull請求被接受的幾率[14,18].
2.3.2 文件優先級
在某些項目中,評審者對優先級高的項目表現更為積極.例如:在WebKit項目中,發現項目優先級和評審積極性之間存在統計學上顯著的相關性,優先級越高的補丁被接受的幾率越大[17,20].
2.3.3 軟件組件
不同的項目組件對代碼評審的時間有一定影響[17].例如,WebKit項目包括bindings,bridge,css,dom,editing,html,inspector,page,platform,rendering等組件,其中,rendering組件需要101分鐘的時間來進行評審,bindings需要72分鐘,inspector需要58分鐘.
2.3.4 組織因素
代碼Pull請求所屬的組織機構對其評審有一定的影響[17].代碼評審過程不僅和技術價值有關,而且和商業利益有關.當Pull請求的擁有者和評審者所在的組織不同時,代碼審核速度會降低.例如,蘋果對自身補丁的審核速度非常快,但對谷歌補丁的審核速度相對較慢.谷歌公司雖然對不同組織的補丁審核速度差異較小,但是,依然能體現出谷歌公司對待不同組織補丁的區別.
2.3.5 應用領域因素
面向開源項目的應用領域比較廣泛,不同領域接受到的請求數量不等,所以,不同領域評審請求被通過的幾率也不一樣.例如,某些項目包含以下幾個領域:Networking、數據庫、IDE、Statistics、Framework、庫和客戶端應用程序.研究者發現Framework和IDE領域接受到的請求數量為最多,其中,被通過的成功幾率也相對高于其他項目[14].
2.3.6 項目的熱度
項目的熱度由項目的存在的時間和被fork的數量來衡量[12,14].隨著時間推移,項目熱度會發生變化,從而,導致項目的Pull請求評審通過的幾率不同.
有效地執行代碼評審可以提高軟件的質量并減少缺陷的發生.但是,這需要具有經驗和對系統的代碼有深刻理解的審閱人員.對于具有一定規模的開源項目,涉及到的人員數量眾多,手動選擇審閱人員是一項昂貴且耗時的任務.面對這一挑戰,自動化推薦是解決該問題的一個有力的工具.因而,最近研究者們通過對不同大型項目研究分析,提出了各種各樣的推薦算法,為Pull請求尋求一個合適的評審人員.
如今,隨著信息技術和互聯網的發展,人們逐漸從信息匱乏的時代走入了信息過載[24].自動推薦系統是建立在海量數據挖掘基礎上的一種高級商務智能平臺[25],它可以為用戶提供個性化的決策支持和信息服務,幫助用戶發現對自己有價值的信息,從而實現信息消費者和信息生產者的雙贏[26].自動推薦技術和系統在許多領域都得到了應用[27],例如,電子商務、電影和視頻網站、個性化音樂網絡電臺、社交網絡、個性化郵件、個性化閱讀等[28,29].推薦算法的本質是通過一定的方式將用戶與物品聯系起來,目前大致有三種方式:基于內容的推薦[30-32]、基于協同過濾的推薦[33-35]和社會化推薦[36-38].由于一個Pull請求并不需要反復被評審,因此,協同過濾的推薦方法無法使用[39].因此,目前采用的評審員推薦方法主要分為基于內容的推薦和社會化推薦兩類.
基于內容的推薦是在推薦引擎出現之初應用最為廣泛的推薦方法,它的核心思想是根據推薦對象的屬性,發現“物品”或者內容的相關性,然后基于用戶以往的偏好記錄,推薦給用戶相似的“物品”[40,42,44].圍繞審閱者推薦,研究者利用了基于文件路徑的相似性、基于信息檢索的方法進行推薦和基于經驗的推薦.
3.2.1 基于文件路徑相似度算法
文獻[1,8,43,44,45]中都采用了文件路徑相似度的算法,該算法的目的是推薦那些曾經評審過相關代碼的評審人員.代碼的相關性可以采用文件路徑的相似性來衡量.該算法的核心思想是建立在一個假設基礎之上:位于類似的文件路徑中的文件是相關的,因此可以有同樣的專家進行代碼評審[8].這個假設背后的理由是:在大多數大型系統中,具有類似功能的文件通常位于相同或相接近的目錄中[46],例如Linux內核項目中,文件目錄結構反映了系統體系結構.
該算法的一般步驟如下:
首先,當目標Pull請求到達時,首先確定Pull請求的相關文件目錄,即提交者將文件提交到的文件目錄.這些文件目錄被視為Pull請求的相關模塊目錄.
其次,在選擇目標Pull請求的候選評審員后,計算該Pull請求與各候選評審員之間的關系.在提交目標Pull請求之前,每個候選人都已經提交或審核過這個模塊相同或相似的文件,因此,通過總結每個相似文件之間的關系來得到Pull請求和評審者之間的關系,如公式(1)所示:
relation(d,pr)=∑pr′:PRd∑f′:Fpr′∑f:Fprsimilarity(f,f′)
(1)
其中,其中,Fpr′表示歷史Pull請求更改的相關文件,Fpr表示為目標Pull請求更改的相關文件,similarity(f,f′)表示兩個文件之間相似度,d代表評審者;PRd指評審者d之前評審過的Pull請求集.可以采用字符串比較具體計算文件目錄的相似性.
最后,在得到每個候選人與目標Pull請求的關系后,得到排名前n的候選人作為推薦結果.
具體而言,文獻[8]中使用了四種字符串比較方法求取文件路徑相似性,這四種方法分別為:最長公共前綴,最長公共后綴、最長公共子串和最長公共子序列.文獻[44]提出求取文件目錄相似性公式,如公式(2)所示:
(2)
上式公式fn,fp分別表示在Pull請求pr所在的同目錄下的兩個文件,max(Length(fn),Length(fp))取兩個文件的長度的最大值,其中commonPath(fn,fp)計算兩個文件路徑中的公共目錄的數量,具體計算方法如下:首先,根據文件路徑,將路徑字符串其目錄分隔符進行切分,得到該文件所處位置的目錄層次列表;然后比較兩文件的目錄前綴,取重合的公共目錄數為得到的結果.例如,對于某安卓項目,有以下兩個文件,分別為/src/camera/photo/a.java和/src/camera/video/a.java,則可得兩者公共祖先目錄為/src/camera文件夾,因而,兩路徑的公共目錄數量為2.
文獻[45]中得出結論,使用該算法準確率高達77.97%,明顯優于基于代碼行對比的Review Bot算法,使得相似性的對比不局限于具體的代碼行,所以泛化能力更強,對不同的項目更為通用.
3.2.2 基于信息檢索推薦算法
文獻[8,49,50-52]中提出了基于信息檢索的推薦算法,該算法的核心步驟如下:
首先,根據項目的描述及標題,為每個項目的Pull 請求生成技術術語集合,而這個術語集合是依據構建的技術術語語料庫刪除之前定義的停止詞來生成的.
其次,根據TF-IDF算法生成每個Pull 請求的向量,其中不同的Pull 請求具有不同的值,如公式(3)所示:
(3)
上式中,t是某個從Pull請求pr中提取的技術術語,freq(t,pr)是t在每個pr中出現的次數,Tpr是在每個Pull請求中所有的技術術語集合,PR表示整個項目的所有Pull請求.
接著,當出現目標Pull請求時,可通過余弦相似度計算Pull請求之間的關系.利用開發人員之前評審過的Pull請求與目標Pull請求之間的關系,得到開發人員與目標Pull請求之間的關系,如公式(4)所示:
(4)
上式中,d是評審者,PRd是評審者d以前審核過的Pull請求集,similarity(pr,pr′)是目標Pull請求pr與歷史Pull請求pr′之間的相似度.因此當目標Pull請求出現,通過計算評審者與目標Pull請求之間的關系,然后按降序排列這些值,并推薦最前面的幾個結果.
文獻[53]中也指出該推薦算法比較簡單,比較適合活躍的評審人員,不適合不活躍的評審人員,總體性能精確度高于Rails Robot(一種自動分配代碼評審人的機器).
3.2.3 基于經驗的推薦
基于文件路徑或檢索的推薦算法均是利用了Pull請求的粗粒度信息.而基于審閱者經驗的推薦算法可以對評審者進行更深入的刻畫.該方法利用代碼的歷史更改來衡量評審者的專業知識,充分考慮評審者歷史的興趣點,從而得出Pull請求與評審者的聯系程度,進而進行評審者推薦[41,54-57].利用遺忘曲線的特性,記憶的強度如公式(5)所示:
(5)
上式中,t表示創建了記憶后經過的時間,s表示記憶強度.在評審者推薦問題中,當一個評審者審閱或提交了一段代碼,則可以認為該評審者擁有了這部分記憶.隨著時間的推移,可以認為該評審者對它的記憶逐漸減弱.
當開發者評審或提交Pull請求時,認為該開發者對這塊領域的相關技術具備一定的知識儲備.然而,不同的Pull請求對應不同文件中的代碼行修改,同時對應的提交和評審時間不一樣.因此,為了計算開發人員對不同Pull請求的知識經驗,需要涉及修改的代碼行及相關的時間.開發者對源代碼文件的經驗知識值如公式(6)所示:
E(d,f)=

(6)
上式中,kT(d,pr)表示由開發者d提交或是評審Pull請求的時間,PRd表示由開發者評審過的Pull請求集合,PRf表示修改文件f中的目標Pull請求集合,loc(pr,f)表示Pull請求pr的相關文件f中更改的代碼行,這里設置的記憶強度為1,忽略不同開發者之間的差異.
開發者和目標Pull請求之間的關系,總結為候選者對目標Pull請求中各個相關文件的經驗知識,如公式(7)所示:
(7)
式中Fpr表示目標Pull請求pr目錄下的文件集合.
該算法考慮到評審者興趣點的歷史變化,對評審者近期的活躍點進行著重考量,使結果更為可信.較以往模型,可以有效的處理評審者興趣轉換的問題,具有積極意義.
社會化推薦是通過用戶自己的社交網絡關系進行信息推薦[61-63],物以類聚,人以群分,好友中越多的人對某條信息感興趣,則可以預測用戶對該條信息的興趣度越大.從而可以利用社會化推薦的方法,來進行評審者推薦.
基于社會化推薦的思想,文獻[12,47,50,54-56]中提出了基于評論網絡的推薦算法,該算法的核心思想是通過尋求共同興趣的開發人員,使之作為一位合適的評審人員.其中,開發者之間的共同興趣可以通過開發者和評審者之間對Pull請求的評論互動來衡量.基于評論網絡,可以預測出與Pull請求高度相關的評審者,從而進行評審者推薦.
評論網絡[54]由有向圖Gcn=
(8)
其中k是結點開發者Vi提交Pull請求的總數,m是VJ在同一個Pull請求中提交的評論的總和,Pc是經過實證的默認值(設置為1),其含義是保留評估每條評論對Pull請求的影響,λ是Pull請求的衰減系數,其值設置為0.8,t(i,j,r,n)為時間敏感因子函數,如公式(9)所示:
(9)
其中timestamp(i,j,r,n)是評審者VJ對貢獻者Vi在第r條Pull請求提交第n條評論的創建時間.其中baseline與deadline與訓練集的選擇高度相關.例如,使用2012年01月01日至2013年05月31日的數據來學習權重,則baseline和deadline分別設置為2011年12月31日和2013年05月31日.
當貢獻者提出新的Pull請求時,使用Pull請求的文本來計算各個候選評審者的專業評分.然后,在評論網絡中,由貢獻者開始,計算各個候選評審者的興趣評分.同時,考慮到共同興趣的影響和專業性的影響都很重要,因而將興趣分數進行歸一化,最后將兩種評分加和起來得到各個評審者的最終評分,并以此選取最大分數的K個評審者進行推薦.
近年來,隨著分布式軟件開發流行,越來越多的開源軟件項目托管在Github管理平臺.GitHub為這些公開的數據提供了REST API[58,60,64],通過調用API接口,研究人員能夠獲取各大型項目的原始數據,如項目開發者信息、代碼庫信息、提交信息、合并信息、Bug 信息等,從而構造高質量且互相關聯的數據.可以從GitHub上獲取詳細的Pull請求的評審信息,此外,還可以使用REST API收集一些流行的大型開源項目數據,如Rails、Angular、Netty、Saltstack等上面的代碼評審信息.
對于評審者推薦結果的評價,研究者們主要使用精確率(Precision)、召回率(Recall)、MMR(Mean Reciprocal Rank)等[48,59,61,65].當模型返回的是排序的K個推薦結果,然后可以根據Top1到TopK的精確率和召回率,以及MMR來得到對模型的評價.
1)精確率:又稱查準率,正確推薦的評審者數目占模型預測的評審者總數的比例.計算如公式(10)所示:
(10)
上式中,Recom_Reviewers(i)代表給第i個Pull請求推薦的評審者,Actual_Reviewer(i)是第i個Pull請求的實際評審員,m是每個項目中測試Pull請求的數量.
2)召回率:又稱查全率,正確推薦的評審者數目占所有評審者數目的比例.其計算如公式(11)所示:
Recall=
(11)
上式中的各變量含義同上.
3)MMR:考察返回的結果集合的優劣情況,較優的結果越靠前,評分越高.其計算如公式(12)所示:
(12)
上式中,K是推薦系統返回結果的個數,rank(i)是第一個相關的結果所在的排列位置.
盡管對開源軟件中代碼評審的研究已經取得了不少成果,但是這些研究還存在一定的局限性,未來需要(但不限于)從以下方面展開研究:
1)盡管研究者已經分析了眾多因素對代碼評審的影響,這些方面的研究還不夠全面和深入.一方面,還有許多因素沒有考慮,例如,評審者的情感、性別等因素沒有研究;第二,各種因素具有復雜的交互作用,目前的研究并沒有考慮因素的交叉影響;第三,目前的許多研究采用的是定性方法,并基于小規模的調研,下一步可以基于更大的數據規模進行定量化的研究.
2)盡管有關代碼評審的影響因素已經有不少研究并取得了相應的成果,但是在評審者推薦中這些因素并沒有得到完整的考慮.例如,研究中表明評審者的工作負荷對Pull請求的處理及時性有影響,如果一位評審者目前有很多請求需要去評審,那么新的評審任務很可能被他拒絕,因此成為一個失敗的推薦.在未來,評審者推薦需要進一步結合多種影響因素.
3)目前的推薦算法都是基于歷史數據來確定評審員是否適合某個Pull請求[13,47,55,56],并基于歷史數據來評價該推薦算法的效果.然而,實際中的代碼評審并不總是成功的,因而,需要結合過去評審者的實際表現進行推薦.
4)隨著開源項目流行,開發者和項目的數量日益俱增,不同的項目具有不同的特點.然而,現有的評審者推薦算法普遍還不具有很強的泛化能力且不能很好的處理概念漂移的問題.甚至不同的項目可能需要不同的推薦算法.因而,評審者推薦算法的適應性也是一個重要的研究方向.
近年來,開源軟件開發得到了迅速發展并涌現出一批成功的開源項目.許多個人乃至企業都參與到開源軟件開發中.然而,開源軟件開發中如何保證軟件開發質量是一個挑戰.其中Pull請求的代碼評審是保證軟件開發質量的重要手段.
圍繞代碼評審的研究已成為一個熱點.研究者們針對影響代碼評審質量的因素、評審者的自動推薦等問題進行了研究并取得了一定的成果.研究表明,請求提交次數、補丁代碼的大小、是否首次提交Pull請求、開發者的身份、開發者與審閱者之間的關系、Pull請求中代碼的位置、開發者的經驗、評審人的活躍度、項目涉及的編程語言、評審隊列長度、文件優先級、組織因素、應用領域因素、項目的熱度等都對評審質量或者評審的及時性和響應性有一定的影響.同時,為了進行代碼評審者推薦,目前的推薦方法中考慮了Pull請求之間的相似性、項目之間技術相關度、開發者之間的社交關聯度等信息.下一步我們需要對更多的影響因素進行研究并應用于評審者推薦算法中.