新聞中心
代碼的 Bug 到底與什么有關(guān)?代碼的行數(shù)?項(xiàng)目的規(guī)模?還是開(kāi)發(fā)者的人數(shù)?在本文中,將基于機(jī)器學(xué)習(xí)模型繪制的圖形,告訴你諸多 Bug 的由來(lái)!

以下為譯文:
怎樣才能減少軟件中的Bug?本文將告訴你傳統(tǒng)觀點(diǎn)是錯(cuò)誤的,下列數(shù)據(jù)會(huì)讓你感到驚訝。
軟件開(kāi)發(fā)人員普遍認(rèn)為,代碼量越大Bug就越多。雖然許多人并不是很清楚這兩者之間的確切關(guān)系,但他們認(rèn)為二者是線性的關(guān)系,即每千行代碼中的Bug數(shù)與代碼量成正比。然而,根據(jù)對(duì)GitHub中10萬(wàn)個(gè)代碼庫(kù)的研究發(fā)現(xiàn),代碼行數(shù)與Bug之間并不存在這種恒定的關(guān)系。而且,代碼行數(shù)并不是Bug數(shù)的可靠指標(biāo)。
注:在本文中,我用“bug”來(lái)指代軟件中從一些從用戶的角度來(lái)看的異常行為,例如:死機(jī)、視覺(jué)異常、不正確的數(shù)據(jù)等?!癇ug”也常用于描述軟件中可利用的缺陷,但這是從黑客的角度來(lái)看。本文不涉及安全漏洞,因?yàn)榘踩┒纯赡苄枰獎(jiǎng)e的模型來(lái)分析。
相反,我們發(fā)現(xiàn)了兩個(gè)更可靠的指標(biāo):貢獻(xiàn)代碼的開(kāi)發(fā)人員數(shù)量和提交代碼的次數(shù)。本文中的圖片使用了一個(gè)擁有兩個(gè)變量的模型,而且這個(gè)模型在預(yù)測(cè)Bug數(shù)目時(shí),與我另一個(gè)擁有16個(gè)變量的模型表現(xiàn)幾乎相同。我會(huì)詳細(xì)解釋這些模型的建模過(guò)程,但是首先:
如果存在這種因果關(guān)系,那么這對(duì)減少Bug意味著什么?
如果你需要可靠的軟件,那么請(qǐng)不要使用會(huì)產(chǎn)生Bug的方法論。例如,敏捷主張直接寫代碼,然后通過(guò)迭代這些代碼來(lái)優(yōu)化需求,所以會(huì)產(chǎn)生很多提交(而提交次數(shù)與bug數(shù)息息相關(guān))。
原型可以減少bug,但是你必須在使用完后丟棄這些原型。你需要通過(guò)數(shù)次提交來(lái)學(xué)習(xí)技術(shù)和客戶的需求,然后編寫一個(gè)非原型版本,其中包含更少量的提交次數(shù)和/或更小的團(tuán)隊(duì)。
刻意保障系統(tǒng)可靠性的工作可能會(huì)產(chǎn)生相反的效果。在采用測(cè)試驅(qū)動(dòng)的開(kāi)發(fā)和單元測(cè)試的情況下,如果提交的代碼次數(shù),或需要的開(kāi)發(fā)人員的話,那么bug數(shù)也會(huì),這可能與你的直覺(jué)恰恰相反。
對(duì)于個(gè)人而言,你應(yīng)該將時(shí)間花費(fèi)在寫代碼之外的事情上,例如思考、設(shè)計(jì)、和制作原型等等。
對(duì)于企業(yè)而言,雇傭的開(kāi)發(fā)人員數(shù)量越少越好,當(dāng)然開(kāi)發(fā)人員的經(jīng)驗(yàn)越多越好。
收集數(shù)據(jù)
首先,我通過(guò)GitHub API,查詢了10萬(wàn)個(gè)項(xiàng)目(超過(guò)135顆星的項(xiàng)目)。這些項(xiàng)目并不是隨機(jī)抽樣,它們占據(jù)了GitHub上高端0.1%,所以我們更加自信會(huì)有很多人發(fā)現(xiàn)和報(bào)告bug。對(duì)于每個(gè)項(xiàng)目,我提取了項(xiàng)目的創(chuàng)建日期(GitHub上的日期),給星數(shù)量,問(wèn)題數(shù)量,提交PR的次數(shù),以及issue tracker是否被禁用。
接下來(lái),我克隆了所有非私有的代碼庫(kù),并直接從Git和文件系統(tǒng)收集了以下統(tǒng)計(jì)信息:
我針對(duì)每個(gè)代碼庫(kù)的HEAD信息,收集了Tokei的統(tǒng)計(jì)信息:每種檢測(cè)到的語(yǔ)言的代碼行數(shù)、注釋、空格等等。然后,對(duì)于每種Tokei檢測(cè)到的語(yǔ)言,我計(jì)算了總字節(jié)數(shù)和LZMA壓縮后的字節(jié)數(shù)。
排名前50的總代碼行數(shù)。被排除的語(yǔ)言(文本和標(biāo)記)用灰色顯示(Text、Html、Markdown、Sg、ReStructuredText)
控制受歡迎度等差異
我們以為,舊項(xiàng)目和受歡迎項(xiàng)目的平均bug數(shù)會(huì)更偏高。為了控制這些差異以及其他差異,我使用了如下模型:
ln(issues) = β1created age + β2first commit age + β3ln(stars) + β4ln(contributors) + β5ln(all commits) +β6ln(code) + β7ln(comments + 1) + β8ln(pull requests + 1) + β9ln(files) + ε
我通過(guò)這個(gè)模型做了擬合,并通過(guò)10折交叉驗(yàn)證測(cè)試了模型與線性回歸的擬合度,然后在一個(gè)組合圖中繪制了每個(gè)折疊的預(yù)測(cè)誤差。在此之前,我刪除了所有私有、歸檔、鏡像和分叉項(xiàng)目,沒(méi)有啟用issue tracker的項(xiàng)目,以及數(shù)據(jù)集中bug數(shù)為零的項(xiàng)目。
9個(gè)變量模型的預(yù)測(cè)誤差
這個(gè)模型有一些偏差,但其他方面的擬合度還不錯(cuò)。它高估了GitHub上問(wèn)題數(shù)量很少(<10)的項(xiàng)目的bug數(shù)(相反低估了問(wèn)題數(shù)量偏高的項(xiàng)目)。我懷疑這是由于github的api中沒(méi)有將分叉項(xiàng)目標(biāo)記出來(lái),還有一些包含第三方代碼的項(xiàng)目導(dǎo)致的。這些項(xiàng)目夸大了與issue>
ln(issues) = β1ln(code) + ε
ln(issues) = β1ln(lzma bytes) + ε
僅包含代碼行或lzma壓縮的代碼字節(jié)的模型(說(shuō)明了語(yǔ)言之間代碼密度的差異)表現(xiàn)同樣糟糕。
用9個(gè)變量的模型擬合完整的數(shù)據(jù)集后,得出了以下近似值:
ln(issues) = 0.022created age – 0.017first commit age + 0.315ln(stars) + 0.071ln(contributors) + 0.266ln(all commits) +0.072ln(code) + 0.034ln(comments + 1) + 0.413ln(pull requests + 1) – 0.069ln(files) – 1.690
我們可以看出,模型中的主導(dǎo)變量是PR數(shù)(0.413)、給星數(shù)(0.315)和提交次數(shù)(0.266)。將這二者與代碼行數(shù)(0.072)和注釋(0.034)相比較,就會(huì)發(fā)現(xiàn)這些差異更加明顯,尤其是再考慮到變量尚未規(guī)范化,而且?guī)缀跛许?xiàng)目中代碼行數(shù)都會(huì)高于PR數(shù)、給星數(shù)或提交次數(shù)。
由于PR數(shù)和給星數(shù)是GitHub特有的功能,我還構(gòu)建了一個(gè)沒(méi)有這兩個(gè)數(shù)據(jù)項(xiàng)的模型。然后,根據(jù)擬合模型的系數(shù),再進(jìn)一步將其簡(jiǎn)化為只包含提交代碼的人數(shù)和提交次數(shù)。這種只有3個(gè)變量的模型的表現(xiàn)幾乎與其他模型完全相同,而且還可以顯示成3G圖形:
ln(issues) = β1first commit age + β2ln(contributors) + β3ln(all commits) + β4ln(code) + β5ln(comments + 1) + β6ln(files) + ε
ln(issues) = β1ln(contributors) + β2ln(all commits) + ε
在刪除了GitHub特有的數(shù)據(jù)項(xiàng)后,提交代碼的人數(shù)和提交次數(shù)就占據(jù)了主導(dǎo)地位,從刪除所有其他變量時(shí)錯(cuò)誤數(shù)輕微的減少就可以看出。
會(huì)不會(huì)是這個(gè)模型搞錯(cuò)了?
現(xiàn)在我們知道了提交代碼的人數(shù)和提交次數(shù)的影響,下面我們來(lái)看看,如果不采用任何根據(jù)提交代碼的人數(shù)和提交次數(shù)繪制圖形的模型,那么代碼行數(shù)與問(wèn)題數(shù)量之間有何關(guān)系。
針對(duì)GitHub,繪制代碼行數(shù)(x軸)與GitHub上的問(wèn)題數(shù)(y軸)的關(guān)系圖,并根據(jù)提交代碼的人數(shù)和提交次數(shù)分組。
為了節(jié)省空間,我沒(méi)有顯示所有的10萬(wàn)個(gè)項(xiàng)目。我按照提交代碼的人數(shù)和提交次數(shù)進(jìn)行了分組,因?yàn)槲矣X(jué)得這種分組方式最有意思,且具代表性。為了避免選擇偏差,我只在選擇分組之后進(jìn)行繪圖。
你只看到了一團(tuán)團(tuán)雜亂的點(diǎn),對(duì)吧?這就對(duì)了:上圖證實(shí)了代碼行數(shù)與bug數(shù)之間的關(guān)聯(lián)性非常弱。而且請(qǐng)記住,這些圖是用對(duì)數(shù)繪制的,而且這個(gè)模型使用的是ln(code)(代碼行數(shù)的對(duì)數(shù)):因?yàn)橄嚓P(guān)性會(huì)隨著代碼行數(shù)的大小而變化。
隨著代碼行數(shù)的增加,bug數(shù)卻增長(zhǎng)緩慢
我見(jiàn)過(guò)有人說(shuō)每千行代碼的bug數(shù)在0.5-50個(gè)。但是我發(fā)現(xiàn)得出這樣的結(jié)論的人只研究了1-2個(gè)成熟的軟件項(xiàng)目在某一個(gè)時(shí)間點(diǎn)或兩個(gè)版本之間的代碼。只查看某個(gè)項(xiàng)目在一個(gè)時(shí)間點(diǎn)的快照,憑什么認(rèn)為這個(gè)項(xiàng)目在早期或后期的情況會(huì)保持不變?
根據(jù)上述數(shù)據(jù),認(rèn)為bug數(shù)和代碼行數(shù)之間存在任何常量的關(guān)系是不明智的。相反,我們應(yīng)該認(rèn)識(shí)到bug數(shù)目增長(zhǎng)的速度會(huì)隨著項(xiàng)目的成熟而越來(lái)越慢。原因是了什么?我認(rèn)為:
我們觀察到的頻率呈對(duì)數(shù)分布,而不是正常分布。一小部分bug能被更快、更頻繁地發(fā)現(xiàn),而系統(tǒng)中處于“長(zhǎng)尾”的bug發(fā)現(xiàn)速度和頻率要低得多。
bug數(shù)量與功能數(shù)有關(guān),而跟代碼行數(shù)無(wú)關(guān),而代碼行數(shù)與功能數(shù)呈超線性分布。(隨著項(xiàng)目的增長(zhǎng),添加新功能所需的代碼行數(shù)會(huì)增加。)
項(xiàng)目的核心應(yīng)該隨著時(shí)間的推移變得更加穩(wěn)定,因?yàn)槲覀儠?huì)修復(fù)bug,但不會(huì)做出重大改變。隨著項(xiàng)目的成熟,新來(lái)的開(kāi)發(fā)人員不太可能改動(dòng)關(guān)鍵的代碼,而且新功能的開(kāi)發(fā)需要的核心變化更少。
那么哪些不是問(wèn)題的bug和不是bug的問(wèn)題呢?
對(duì)于這種大小和范圍的研究,GitHub的issue是我所知道的記錄bug的形式。自動(dòng)bug檢測(cè)軟件僅適用于某些語(yǔ)言,而且只能檢測(cè)到“結(jié)構(gòu)性”的bug(比如無(wú)效的內(nèi)存訪問(wèn)),而卻無(wú)法檢測(cè)到邏輯錯(cuò)誤(例如錯(cuò)誤的計(jì)算),而且手動(dòng)統(tǒng)計(jì)bug數(shù)是不切實(shí)際的(或者根本不可能)。我們必須假設(shè)處于開(kāi)放狀態(tài)的issue能夠代表用戶遇到的bug數(shù)。
異常值和替代假設(shè)
在查看這些數(shù)據(jù)之前,我沒(méi)有猜到僅靠提交代碼的人數(shù)就可以預(yù)測(cè)bug數(shù)。這表明項(xiàng)目的開(kāi)發(fā)人員數(shù)量蘊(yùn)含了有關(guān)項(xiàng)目的其他大量信息。一種合理的解釋是“大型開(kāi)發(fā)團(tuán)隊(duì)有向平均數(shù)回歸的趨勢(shì)”:即隨著團(tuán)隊(duì)開(kāi)發(fā)人員數(shù)量的增加,項(xiàng)目的提交次數(shù)/功能/代碼行數(shù)與開(kāi)發(fā)人數(shù)的比率傾向于一個(gè)平均值。
隨著開(kāi)發(fā)人員數(shù)量的增加,代碼行數(shù)的范圍變窄。
在瀏覽異常值時(shí),我遇到了一個(gè)特別有趣的類別:游戲機(jī)模擬器。該類軟件擁有測(cè)試輸入(游戲),測(cè)試人員(游戲玩家)和其他實(shí)現(xiàn)(其他模擬器和系統(tǒng)本身)等數(shù)據(jù),可以為將來(lái)的軟件bug數(shù)的比較研究提供更加可控的實(shí)驗(yàn)環(huán)境。
分享標(biāo)題:怎樣才能減少軟件中的Bug?數(shù)據(jù)顯示程序員才是制造Bug的“元兇”
網(wǎng)頁(yè)URL:http://www.dlmjj.cn/article/dpdojch.html


咨詢
建站咨詢
