千行代碼缺陷率是一個很常用的統(tǒng)計質(zhì)量的指標。十幾年前是一個非常通用的參考指標。
時至今日,仍然有很多組織在用這個指標作為質(zhì)量的參考依據(jù)聂示。
那么什么是千行代碼缺陷率呢?下面這個公式解釋了千行代碼缺陷率的構(gòu)成簇秒。
按照上述的公式來看鱼喉,缺陷的數(shù)量越少表示質(zhì)量越高。而生產(chǎn)的代碼越多宰睡,可以容忍的bug數(shù)量也就越多蒲凶。那么這個公式應(yīng)該是可以很好地檢測代碼質(zhì)量的。
然而拆内,事情并不是這么簡單的旋圆。看事情要從多個角度來看。讓我們站在程序員的角度來看看這個事情是什么樣的吧麸恍。
小明(為毛總是他)是一個很挫的程序員灵巧,基本上他的工作就是每天生產(chǎn)bug搀矫。他左邊的小剛是個很優(yōu)秀的程序員,他每天的工作就是如何使得代碼更精煉刻肄,提高代碼的可讀性瓤球,可擴展性和可變更性。他右邊的小美是個很上進的程序員敏弃,每天都在努力的想要學習小剛那種優(yōu)雅的寫代碼的方式卦羡。
一個周期下來,公司開始考核質(zhì)量了麦到。
小明在這期間總共寫了2萬行代碼绿饵。其中留到測試發(fā)現(xiàn)bug數(shù)量有162個,符合公司對于質(zhì)量的預(yù)期瓶颠,每千行代碼的bug數(shù)7-10個拟赊。小明得到了贊賞。
小剛在這期間總共寫了4000行代碼粹淋,其中留到測試發(fā)現(xiàn)的bug數(shù)量為12個吸祟,遠遠低于公司對于bug的虛榮范圍。負責測試他的代碼的人被責令要繼續(xù)加強測試桃移。
小美在這期間寫的代碼行數(shù)也是4000行屋匕。其中留到測試發(fā)現(xiàn)的bug數(shù)量有53個,超過了公司的質(zhì)量預(yù)期范圍谴轮,屬于差的一等炒瘟。小美被責令改進代碼質(zhì)量。
他們的質(zhì)量狀況統(tǒng)計如下:
為什么事實和理想之間的差距這么大第步?小剛是個優(yōu)秀的的程序員用4000行代碼實現(xiàn)了小明用20000行代碼實現(xiàn)的功能疮装。并且通過自己的自動化測試,使得質(zhì)量得到有效的保證粘都,但是卻得到了一個“測試不充分”的評價呢廓推?
為什么努力像小剛一樣寫優(yōu)秀代碼的小美得到了一個差評呢?
那么之后他們的行為又會由于得到這樣的不公正的待遇走向何方呢翩隧?
沒過多久樊展,需求發(fā)生了變更。小剛和小美的代碼具有充分的柔軟性堆生,可以很優(yōu)雅的應(yīng)對變更专缠。
并且沒有引入新的問題。而小明寫的意大利面條式代碼(Spaghetti Code)淑仆,則由于復(fù)雜性提高涝婉,而引入了新的上百個Bug。但是由于代碼規(guī)模大蔗怠,所以在原來的考核標準下墩弯,小明仍然得到了好評吩跋。而小剛和小美則繼續(xù)得到中評或者差評,因為他們的工作看起來太簡單了渔工。
很顯然锌钮,這個指標已經(jīng)不能夠正確的反映質(zhì)量狀況了。那么到底是什么地方出了問題引矩?又應(yīng)該如何改正呢梁丘?
首先,這是個目標和方法背道而馳的指標旺韭。
程序員短期之內(nèi)水平飛速提升的可能性基本上不存在兰吟,而作為程序員面臨這個公式的最佳策略是稀釋代碼。下面是程序員的策略圖
所以茂翔,選擇稀釋代碼是個最簡單的策略。那么稀釋代碼的最佳策略是什么履腋?復(fù)制粘貼
復(fù)制粘貼的最大問題是什么珊燎?引入更多的bug(請參考DRY原則?)。為了能夠提高質(zhì)量的最佳策略竟然是引入更多的問題遵湖!這就是這個指標帶來的問題之一悔政。
問題之二是,這個指標帶來的隱含意思是延旧,向團隊宣布:我們不歡迎那些程序?qū)懙暮玫某绦騿T谋国。
就像上例所提到的,寫的好的小剛迁沫,和正在努力寫得好的小美都得不到好評芦瘾。至于那個無稽的
7-10個/千行的指標(這個數(shù)字是被廣泛使用的一個數(shù)字)更是莫名其妙。這個的潛在意思是“我不相信你能夠?qū)懗鰜砀哔|(zhì)量的代碼”集畅。WTF近弟??
問題之三是強湊Bug挺智。當QA團隊也要面臨這個指標考核的時候祷愉,他們會怎么做?一個bug拆開寫赦颇,同一個原因的bug分開記錄二鳄,這樣可以湊到這個指標區(qū)間,來粉飾數(shù)據(jù)媒怯。
這些假數(shù)據(jù)對于決策有什么幫助呢订讼?
同樣的,千行代碼生產(chǎn)率這個指標沪摄,也需要放棄躯嫉。
這背后的最重要的原因就是:
功能的多少和代碼行數(shù)不成正比關(guān)系纱烘,甚至也不呈現(xiàn)正相關(guān)關(guān)系。
比如祈餐,我寫的一套Java代碼框架擂啥,允許定義頁面的操作為空白。
比如:
@Controller
@RequestMapping("/books")
public class BookController extends CrudBaseController {}
就可以完成對圖書的增刪改查操作帆阳。
增加一組新的功能哺壶,只要幾行代碼而已。有的時候增加新功能甚至是需要減少代碼行數(shù)的蜒谤。
所以山宾,凡是以代碼行數(shù)來統(tǒng)計什么的指標都是不可靠的。
有人會說鳍徽,我們的公司不會有人故意稀釋代碼资锰,所以代碼行數(shù)在我們這里是可以使用的指標。
這個推論并不成立阶祭。因為代碼行數(shù)和質(zhì)量并無任何直接關(guān)系绷杜。這就好像是扔磚頭看風向一樣。自欺欺人而已濒募。
那么鞭盟,說了這么多,不這么考核質(zhì)量瑰剃,怎么考核質(zhì)量呢齿诉?有幾個常用的可靠指標,推薦給大家
1. 圈復(fù)雜度(Cyclomatic Complexity)?
簡單的說圈復(fù)雜度越高的代碼會有越多的Bug晌姚,這個是業(yè)已被證明了的粤剧。圈復(fù)雜度反應(yīng)了代碼的耦合度。都要寫低耦合高內(nèi)聚的代碼舀凛,那么這個指標就可以幫助更好地了解代碼的耦合度情況俊扳。
推薦的圈復(fù)雜度不要超過10,如果實在做不到猛遍,那么不要超過20馋记。
如果你的團隊代碼的圈復(fù)雜度已經(jīng)超過100了,你可能需要考慮些大動作了懊烤。
測量圈復(fù)雜度的工具也有很多梯醒。下面推薦幾個:
Source Insight
Code Metrics
Cobertura
2. 平均缺陷修復(fù)時間(Mean Time To Repair)?
發(fā)生缺陷并不可怕宾茂,可怕的是修復(fù)的時間過長美莫。假設(shè)每個缺陷修復(fù)時間只要幾分鐘萧锉,那么有幾十個Bug秦士,修復(fù)的總計時間也并不會太長。而平均一個Bug修復(fù)需要3天的那種(其中2天都在調(diào)查問題根源)钝荡,基本上代碼扔掉重寫的成本都會比在補丁上繼續(xù)打補丁的成本要低得多愉适。
平均缺陷修復(fù)時間能夠更好地反映代碼本身的質(zhì)量狀況酸役,以及團隊的成熟程度。
往往平均修復(fù)時間較長的代碼都是復(fù)雜度高猫胁,耦合度高的代碼箱亿。而平均修復(fù)時間短的代碼都是結(jié)構(gòu)相對清晰,命名規(guī)范弃秆,容易理解届惋,擴展和變更的代碼。
如果你的公司還在使用“千行代碼缺陷率”菠赚,你把這篇文章轉(zhuǎn)給相關(guān)人員看看吧脑豹。