段雨佳,鞠 婷
(杭州電子科技大學(xué) 計算機學(xué)院,浙江 杭州 310000)
代碼審查指通過閱讀代碼來檢查源代碼的編碼規(guī)范以及代碼質(zhì)量和功能是否達到預(yù)期的一項活動。代碼審查最初在軟件審查中提出,主要是為了發(fā)現(xiàn)在軟件開發(fā)初期未發(fā)現(xiàn)的錯誤并進行修正,從而達到提升軟件質(zhì)量和開發(fā)者的技術(shù)水平的目的。在實際軟件開發(fā)過程中,許多開源項目和商業(yè)軟件采用同行代碼審查的方式[1]。即由項目中的一名開發(fā)者作為代碼審查人,對項目中其他開發(fā)人員所編寫的代碼進行審查,在代碼通過審查后,再判斷代碼是否可以并入主代碼倉庫。然而,在現(xiàn)代大型軟件開發(fā)中,代碼審查的方式通常借助工具進行,以輕量級和非正式的方法為主。比如常見的審查工具:基于git的版本控制系統(tǒng)Gerrit[2]。
Capers Jones通過分析12 000多種軟件項目后發(fā)現(xiàn),通過正式的代碼審查可以發(fā)現(xiàn)項目中60%到65%的潛在缺陷,非正式代碼審查可以發(fā)現(xiàn)約50%的潛在缺陷,而測試只能發(fā)現(xiàn)30%的潛在缺陷[3]。因此,代碼審查被認(rèn)為是提高整體軟件質(zhì)量和降低后期風(fēng)險的重要保證機制[4]。Remillard J等人的研究表明,為了確保代碼審查的有效性,審查時間需要大于開發(fā)時間的1/4[5]。此外,代碼審查不僅可以提高項目人員的開發(fā)經(jīng)驗、項目的熟悉度和業(yè)務(wù)邏輯能力,還可以促進項目人員之間相互學(xué)習(xí)。因此,提高代碼審查的質(zhì)量和效率,對于降低軟件開發(fā)成本和提高軟件質(zhì)量有重要意義。由于代碼審查評論是在代碼修改提交下一個版本的補丁之前所提供的修改意見,有效的代碼評論不僅可以幫助開發(fā)人員更好的實施代碼審查,而且對于提高代碼質(zhì)量也有著非常重要的意義。有研究表明:約有65%以上的開發(fā)人員會根據(jù)代碼評審人員的評論意見對代碼進行修改和完善[6],因此高質(zhì)量的代碼審查意見顯得尤為重要。根據(jù)Mohammad等人研究調(diào)查,在ABC公司的1 116條代碼審查意見中,約有44.47%的意見是無用的。
為了實現(xiàn)對代碼審查意見的有效性進行分析從而提高代碼審查的質(zhì)量和效率,本文根據(jù)代碼審查過程中產(chǎn)生的數(shù)據(jù),提出一種基于深度學(xué)習(xí)LSTM(Long-Short Term Memory)[8]的代碼評審意見有效性評估方法,從代碼審查意見數(shù)據(jù)中提取與意見有效性相關(guān)的語義特征,從而有效的協(xié)助開發(fā)人員判斷評審意見的有效性,以提高代碼審查的質(zhì)量并減少軟件開發(fā)的時間。本文的主要貢獻是:本文提出了一種基于深度學(xué)習(xí)的代碼審查意見語義特征的提取方法,并基于此方法挖掘?qū)彶橐庖娭姓Z義的序列關(guān)系和空間關(guān)系,使用Word2Vec方法[20]對審查意見進行序列化,根據(jù)代碼審查意見中提取的語義特征,構(gòu)建基于語義特征的代碼審查意見有效性預(yù)測模型。為了驗證模型的有效性,本文采集了GitHub上352個開源Eclipse項目在Gerrit[8]中的相應(yīng)的代碼審查意見作為實驗數(shù)據(jù),并進行了廣泛的實驗。實驗結(jié)果表明,該模型可有效的評估代碼審查意見。
自代碼審查1976年提出以來,許多研究人員都針對減少代碼審查工作量進行了不同的探索。Jeong G等人通過預(yù)測補丁修復(fù)意見是否被采納來提高代碼審查工作效率。Thongtanunam P[9]等人通過建立自動推薦代碼審查人模型,從而減少代碼審查工作量。Mohammad[10]等人發(fā)現(xiàn)代碼審查雖然現(xiàn)在被廣泛使用,但其中包含大量無意義的審查意見,并基于這種現(xiàn)象提出了RevHelper模型,一種可以幫助開發(fā)人員自動的預(yù)測審查意見是否有意的模型。這種模型在1 482份代碼審查報告中命中率達到66%。因此代碼審查意見質(zhì)量的高低直接影響著代碼審查的效果和效率。由于深度學(xué)習(xí)在圖像識別、文本分類等方面表現(xiàn)的十分優(yōu)異,許多研究人員都采用了深度學(xué)習(xí)的方法進行了軟件工程的研究。比如:Hu Xing等人利用深度學(xué)習(xí)LSTM模型構(gòu)建代碼缺陷修復(fù)人的推薦模型,在單項目中推薦修復(fù)準(zhǔn)確率達到58%[11]。
代碼審查是人工手動的對源代碼進行評估,主要作用是為識別代碼缺陷并提高代碼質(zhì)量。傳統(tǒng)的代碼審查方式在大型和分布式軟件開發(fā)中受到了限制,因此MCR(Modern Code Review,現(xiàn)代代碼審查)成為了當(dāng)代代碼審查的主要方式。MCR是一種基于工具的代碼審查系統(tǒng),并不像傳統(tǒng)代碼審查那樣正式。本文使用代碼審查系統(tǒng)Gerrit中的代碼審查意見作為實驗數(shù)據(jù),Gerrit作為當(dāng)前比較流行的代碼審查工具,在許多開源項目中得到了有效應(yīng)用。Gerrit的主要審查過程如下:開發(fā)人員對一個代碼文件修改后將代碼提交至Gerrit系統(tǒng)等待審查人員審查,審查人員對待審查文件進行檢查,發(fā)現(xiàn)問題后將會在評論區(qū)給出修改意見,Gerrit將待修改文件和審查意見返回給開發(fā)者,開發(fā)者根據(jù)修改意見進行修改并將修改后的文件進行提交,當(dāng)審查者審查通過后再合并到主代碼庫中。
Word2Vec是Google公司在2013年提供的一種用于詞向量訓(xùn)練的軟件工具。它可以通過一層神經(jīng)網(wǎng)絡(luò)將One-hot(獨熱編碼)形式的詞向量[20]通過訓(xùn)練后達到詞向量到分布形式詞向量的映射。Word2Vec使用一層神經(jīng)網(wǎng)絡(luò)將One-hot形式的詞向量映射到分布式形式的詞向量。使用SGD(隨機梯度下降)[13]的優(yōu)化算法計算損失,最終通過反向傳播算法將神經(jīng)元的權(quán)重和偏置進行更新。最終將One-hot形式的詞向量轉(zhuǎn)換為包含更多語義關(guān)系的Word2Vec形式的詞向量。其中主要依賴CBOW模型(Continuous Bag-of-Words Model)和Skip-gram模型[13]。
深度學(xué)習(xí)是機器學(xué)習(xí)的新領(lǐng)域,它的目標(biāo)在于通過建立模擬人腦的神經(jīng)網(wǎng)絡(luò),運用人腦的學(xué)習(xí)機制來解釋和分析數(shù)據(jù),從而達到對數(shù)據(jù)本質(zhì)特征更好的提取,提高預(yù)測的準(zhǔn)確性[14]。LSTM是一種特殊的RNN(Recurrent Neural Network),LSTM的提出是為了解決RNN的缺點,即對于長序列的梯度向量會存在呈指數(shù)增長或減少,使用RNN難以學(xué)習(xí)序列中的長距離的相關(guān)性。它通過引入“門”的結(jié)構(gòu)實現(xiàn)對信息的控制和保護,使其能夠長時間保存細胞的狀態(tài)從而解決了RNN學(xué)習(xí)長期依賴性的問題[8]。
如圖1所示,這是一個LSTM的單元結(jié)構(gòu)。它通常包含3個門的結(jié)構(gòu)、3個輸入和兩個輸出。3個門分別為輸入門、輸出門和遺忘門,3個輸入為上一LSTM單元的細胞狀態(tài)輸出、上一層的輸出和當(dāng)前層的輸入。門的設(shè)置通常包含一個Sigmoid[15]神經(jīng)網(wǎng)絡(luò)層和一個點積乘法操作。這些門可以打開或關(guān)閉,用于將判斷模型網(wǎng)絡(luò)的記憶態(tài)(之前網(wǎng)絡(luò)的狀態(tài))在該層輸出的結(jié)果是否達到閾值從而加入到當(dāng)前該層的計算中。每個LSTM單元包含:輸入門xt,忘記門ft,輸出門ot,存儲細胞狀態(tài)單元ct,門控矢量it。由于遺忘門會根據(jù)細胞的輸入輸出信息對傳送的數(shù)據(jù)信息進行更新,從而達到對訓(xùn)練時梯度此刻的收斂性和保持重要東西的長期記憶的控制能力。
本文提出使用深度學(xué)習(xí)LSTM網(wǎng)絡(luò)構(gòu)建代碼審查意見價值評估模型,該模型的工作流程如圖2所示。該方法主要分為構(gòu)建模型和評估模型兩個階段。在構(gòu)建模型階段主要為3個步驟:(1)獲取代碼審查意見數(shù)據(jù)并對其進行清洗和預(yù)處理;(2)將預(yù)處理后數(shù)據(jù)轉(zhuǎn)化為詞向量形式的數(shù)據(jù);(3)通過深度學(xué)習(xí)LSTM網(wǎng)絡(luò)將輸入的詞向量數(shù)據(jù)進行學(xué)習(xí),獲取與代碼評審意見價值相關(guān)的特征并使用這些特征構(gòu)建代碼評審價值評估模型。在評估階段,使用模型進行質(zhì)量評估階段,向模型輸入新的代碼審查意見,判斷審查人所給意見的有效性。
本文的數(shù)據(jù)獲取主要來源于GitHub開源社區(qū)的232個Eclipse項目,通過Gerrit獲取這些項目的代碼審查報告。在代碼審查報告中,本文主要使用代碼審查意見和審查報告來源。由于提交的代碼在審查時發(fā)現(xiàn)問題后,系統(tǒng)將會把代碼審查意見返回給代碼提交人員,開發(fā)人員將會根據(jù)審查意見對代碼進行二次修改,直到代碼評審人同意通過后再將代碼歸并到代碼庫中。開發(fā)人員對代碼進行修改后,代碼審查報告會隨之產(chǎn)生對應(yīng)的3種狀態(tài)。這3種狀態(tài)分別為:Replay、Quote和Done,它們的含義分別表示:開發(fā)人員已查看并回復(fù)、已查看但認(rèn)為無需修改和已查看并按照修改意見進行修改。由于狀態(tài)為Done的代碼為開發(fā)人員接受意見并按照審查意見進行了修改,其他狀態(tài)多為不接受意見或者認(rèn)為無需修改。因此本文根據(jù)代碼審查報告中包含修改意見提交代碼的不同狀態(tài),將狀態(tài)為Done的代碼審查意見當(dāng)作是質(zhì)量過關(guān)的審查意見并標(biāo)記為1,其他狀態(tài)為無效的代碼審查意見并標(biāo)記為0。
本文根據(jù)數(shù)據(jù)集的特點,對數(shù)據(jù)進行如下處理:
(1)無意義數(shù)據(jù)的處理。由于每份代碼審查報告中的每條審查意見都對應(yīng)著源代碼的某一行信息、代碼審查意見的提交時間和所屬分支等數(shù)據(jù),因此所獲取的審查意見數(shù)據(jù)對于構(gòu)建審查意見評估模型并不都是有效果的。而這些數(shù)據(jù)增加了特征提取難度和后期模型訓(xùn)練時間,因此本文選擇過濾這些數(shù)據(jù);
(2)停用詞處理。在數(shù)據(jù)集中,存在很多對于特征提取無意義的詞匯,例如:we,in,on,and等。為降低后期噪聲數(shù)據(jù)對模型的影響,本文選擇對這類文本數(shù)據(jù)進行清洗;
(3)特殊詞匯處理。由于在分詞時按照空格或逗號劃分語句,可能會出現(xiàn)專有詞匯被劃分成多個詞(例如,項目名為:papyrus/org.eclipse.papyrus,分詞后為:papyrus、org、eclipse和papyrus)。這樣將會導(dǎo)致審查意見特征缺失。針對這種情況,本文對含有特殊意義的詞匯使用“[]”進行標(biāo)記,在分詞時不處理被“[]”標(biāo)記的內(nèi)容。
由于在使用深度學(xué)習(xí)方法對數(shù)據(jù)進行訓(xùn)練時,所輸入的數(shù)據(jù)是機器可識別的序列化數(shù)據(jù),因此需要將現(xiàn)有文本數(shù)據(jù)轉(zhuǎn)化為計算機可識別的數(shù)據(jù)。本文使用的詞向量化方法為Word2Vec的基于Hierarchical Softmax的CBOM模型[14]。在CBOM模型中,根據(jù)輸入的訓(xùn)練樣本數(shù)據(jù),通過模型計算輸入實驗數(shù)據(jù)中每個詞對應(yīng)的詞向量表示,并將此詞向量作為構(gòu)建審查意見評估模型的輸入數(shù)據(jù)。
代碼審查意見評估模型的目標(biāo)是根據(jù)代碼評審意見和提交代碼過程中的源代碼來源信息評估審查人所給出的審查建議是否有價值。本文提出評估模型結(jié)構(gòu)圖如圖3所示,主要包括3個部分:(1)輸入層:將文本建模后得到的數(shù)據(jù)作為下一層的輸入數(shù)據(jù);(2)特征提取層:將輸入層的輸出數(shù)據(jù)作為LSTM模型的輸入,獲取與代碼審查意見評估標(biāo)準(zhǔn)相關(guān)的特征;(3)輸出層:根據(jù)代碼審查意見評估其是否有價值。
在輸入層中,輸入的數(shù)據(jù)為訓(xùn)練數(shù)據(jù)經(jīng)過文本建模后的詞向量數(shù)據(jù),由于訓(xùn)練數(shù)據(jù)的相應(yīng)的分類標(biāo)簽為1或0,所以對標(biāo)簽數(shù)據(jù)本文選擇直接使用。但由于輸入的數(shù)據(jù)量過大,所以在這一層中,加入了一層Embedding層[16]用于對輸入數(shù)據(jù)進行降維,最終構(gòu)建詞向量矩陣。最終將這一層的輸出數(shù)據(jù)作為特征提取層的輸入。
(1)
hi=ot×tanh(Ci)ot=σ(Wo·[hi-1,xi]+bo)
(2)
fi=σ(Wf·[hi-1,xi]+bf)
(3)
(4)
在此過程中,本文設(shè)置3個門的激活函數(shù)為Sigmoid函數(shù),輸出的激活函數(shù)為tanh函數(shù),損失函數(shù)l為式(5)。根據(jù)損失函數(shù)和各層的輸出使用梯度下降法最終得到最優(yōu)解、各偏置向量和權(quán)重矩陣。詞向量數(shù)據(jù)經(jīng)過LSTM網(wǎng)絡(luò)層加工后得到代碼審查意見的相關(guān)特征。
l(i)=f(h(i),y(i))=‖h(i)-y(i)‖2
(5)
如圖3所示,在經(jīng)過LSTM訓(xùn)練后得到了代碼審查意見的特征,為完成特征到審查意見評估標(biāo)簽的轉(zhuǎn)換,本文使用Softmax分類器[18]作為最終的評估結(jié)果,此處選用交叉熵作為分類的損失函數(shù),計算方法如式(6)所示。
(6)
其中,y表示期望預(yù)測出的評估結(jié)果;y′表示實際模型輸出的評估結(jié)果;x表示詞向量數(shù)據(jù)集;n為數(shù)據(jù)總量。
通過輸入層、特征提取層和輸出層后,本文構(gòu)建了訓(xùn)練階段的模型。通過對現(xiàn)有代碼審查報告審查意見和項目數(shù)據(jù)進行訓(xùn)練,通過不斷調(diào)整模型的參數(shù),達到損失函數(shù)最小化,從而構(gòu)建代碼審查意見評估模型。本文選用了AdamOptimizer作為參數(shù)優(yōu)化器。同時在訓(xùn)練過程中,為了防止過擬合現(xiàn)象的產(chǎn)生,本文采用Dropout策略[19],設(shè)置dropout比率為0.3,即在每次迭代中隨機放棄一部分訓(xùn)練好的參數(shù)。在預(yù)測階段,模型的輸入為一條代碼審查意見,評估模型將會評估該審查意見是否有意義。
實驗采用GitHub上開源的Eclipse項目在Gerrit上相應(yīng)的代碼審查報告作為數(shù)據(jù)集。在清洗無效數(shù)據(jù)后,從67 534份代碼審查報告中獲取了81 414代碼審查意見,涵蓋352個項目,852個用戶,其中被接受即狀態(tài)為Done的審查意見34 064條,其他狀態(tài)47 350條。本文將提取代碼審查報告中的項目名稱和代碼審查意見作為實驗數(shù)據(jù),并根據(jù)代碼審查評論的狀態(tài)作為其分類標(biāo)簽。如果審查意見被接受則設(shè)置該審查意見的標(biāo)簽為1,否則設(shè)置為0。最終,實驗對象由代碼審查評論、審查報告項目名稱和分類標(biāo)簽組成。
由于模型評估的準(zhǔn)確性與參數(shù)的設(shè)置有關(guān)系,因此需要進行模型參數(shù)的調(diào)整。在這一步驟中,本文根據(jù)實驗結(jié)果主要考慮了兩個參數(shù)對實驗的影響:(1)batch_size(批大小);(2)max-length(一條代碼審查意見的編碼長度)。首先在batch_size的選取上,通過實驗發(fā)現(xiàn)batch_size為60時效果最好。實驗結(jié)果如圖4所示。由于max-length大小相差很大,因此將根據(jù)max-length的分布分別設(shè)置max-length。實驗結(jié)果如圖5所示,結(jié)果顯示當(dāng)max-length設(shè)置約為800時評估模型準(zhǔn)確性最好。
在實驗中,為保證實驗結(jié)果的準(zhǔn)確性,本文對每個方法都運行10次,并在運行過程中使用10折交叉驗證方法對模型進行測試,最終取10次平均值作為該模型的結(jié)果。為研究不同方法對評估模型的影響,本文使用準(zhǔn)確率(Accuracy)、召回率(Recall)和F1分?jǐn)?shù)3個指標(biāo)評估模型,計算方法如式(7)~式(9)所示。
(7)
(8)
(9)
其中,tp為被正確地劃分為正例的個數(shù);fp為被錯誤地劃分為正例的個數(shù);fn為被錯誤地劃分為負(fù)例的個數(shù);tn為被正確地劃分為負(fù)例的個數(shù);Precision表示預(yù)測的精確度,計算公式如式(10)所示。
(10)
本文的主要目標(biāo)是根據(jù)輸入的代碼審查意見通過評估模型判斷輸入的審查意見對軟件開發(fā)人員是否有意義,從而減少代碼審查周期和成本。因此,本文主從以下3個問題探究使用本文方法構(gòu)建該評估模型的有效性。
RQ1:基于深度學(xué)習(xí)LSTM的方法構(gòu)建代碼審查意見評估模型是否比其它方法更有效?
由于本文目標(biāo)是建立合適的代碼審查意見評估模型,因此訓(xùn)練模型的選取對于構(gòu)建合適的評估模型十分重要。因此本文也選取了其它訓(xùn)練方法用于構(gòu)建評估模型用于驗證現(xiàn)有模型的有效性。本文分別選取了以下3個機器學(xué)習(xí)方法:樸素貝葉斯(Bayes)、支持向量機(SVM)和LSTM模型非常相近的循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)。實驗結(jié)果如表1所示,結(jié)果顯示使用LSTM方法構(gòu)建評估模型準(zhǔn)確率最高,分別比Bayes方法、SVM方法和RNN方法高出了。因此,使用LSTM方法構(gòu)建代碼審查意見評估模型是十分有效的。
表1 LSTM方法與其他方法比較結(jié)果
RQ2:實驗數(shù)據(jù)集的選取是否對評估模型有影響?
由于本文實驗數(shù)據(jù)來自352個項目,共有800多位人員給出了代碼意見。因此存在對同一個項目,代碼審查意見可能有很大的相似性。這導(dǎo)致了訓(xùn)練模型難以提取代碼審查意見的評估特征。 因此本文根據(jù)每個項目包含的審查意見數(shù)據(jù)量,分別選取了項目數(shù)據(jù)量約為50、100、200、500、1 000、2 000、4 000的7個項目作為實驗對象,實驗結(jié)果如圖6所示。結(jié)果表明,對于同一個項目的代碼審查意見,評估模型準(zhǔn)確率最高達到92.1 %,最低為83.8 %,這可能是由于代碼審查意見的相似性和審查人的選取導(dǎo)致了評估模型的準(zhǔn)確率發(fā)生了浮動。
RQ3:在構(gòu)建模型時,如果使用其他文本建模方法是否對實驗結(jié)果有影響?
由于文本建模目的是將代碼審查意見轉(zhuǎn)化為包含更多語義信息的序列化數(shù)據(jù),因此文本模型的選取對于包含更多原始數(shù)據(jù)信息十分重要。針對本文選取的Word2Vec詞向量模型是否比其他構(gòu)建詞向量方法更有意義問題,本文分別選取了One-hot編碼[20]、Skip模型和Word2Vec模型分別進行了實驗。實驗結(jié)果如表2所示。結(jié)果顯示,采用One-hot的訓(xùn)練后的詞向量方法表現(xiàn)的很差,Skip模型表現(xiàn)一般,而Word2Vec方法表現(xiàn)的最好。因此本文選取的Word2Vec方法對于本文數(shù)據(jù)構(gòu)建詞向量化是十分有用的。
表2 不同文本建模方法在訓(xùn)練模型后結(jié)果
本文使用深度學(xué)習(xí)LSTM方法,通過對開源Eclipse項目的代碼審查報告中的審查意見進行訓(xùn)練學(xué)習(xí),得到了代碼審查意見評估模型。通過實驗,結(jié)果顯示該模型的準(zhǔn)確率在352項目下為88.4%,比其它機器學(xué)習(xí)方法(貝葉斯分類法、支持向量機分類法和循環(huán)神經(jīng)網(wǎng)絡(luò)等方法)有很大的提高。在接下來的研究中,由于審查意見的長度相差較大,期望可以使用混合模型的方法對篇幅較長和極短的審查意見進行進一步的劃分,從而達到提高該評估模型的準(zhǔn)確性。