千行代碼缺陷率是一個很常用的統計質量的指標。十幾年前是一個非常通用的參考指標。
時至今日,仍然有很多組織在用這個指標作為質量的參考依據。
那么什么是千行代碼缺陷率呢?下面這個公式解釋了千行代碼缺陷率的構成。
按照上述的公式來看,缺陷的數量越少表示質量越高。而生產的代碼越多,可以容忍的bug數量也就越多。那么這個公式應該是可以很好地檢測代碼質量的。
然而,事情并不是這么簡單的。看事情要從多個角度來看。讓我們站在程序員的角度來看看這個事情是什么樣的吧。
小明(為毛總是他)是一個很挫的程序員,基本上他的工作就是每天生產bug。他左邊的小剛是個很優秀的程序員,他每天的工作就是如何使得代碼更精煉,提高代碼的可讀性,可擴展性和可變更性。他右邊的小美是個很上進的程序員,每天都在努力的想要學習小剛那種優雅的寫代碼的方式。
一個周期下來,公司開始考核質量了。
小明在這期間總共寫了2萬行代碼。其中留到測試發現bug數量有162個,符合公司對于質量的預期,每千行代碼的bug數7-10個。小明得到了贊賞。
小剛在這期間總共寫了4000行代碼,其中留到測試發現的bug數量為12個,遠遠低于公司對于bug的虛榮范圍。負責測試他的代碼的人被責令要繼續加強測試。
小美在這期間寫的代碼行數也是4000行。其中留到測試發現的bug數量有53個,超過了公司的質量預期范圍,屬于差的一等。小美被責令改進代碼質量。
他們的質量狀況統計如下:
為什么事實和理想之間的差距這么大?小剛是個優秀的的程序員用4000行代碼實現了小明用20000行代碼實現的功能。并且通過自己的自動化測試,使得質量得到有效的保證,但是卻得到了一個“測試不充分”的評價呢?
為什么努力像小剛一樣寫優秀代碼的小美得到了一個差評呢?
那么之后他們的行為又會由于得到這樣的不公正的待遇走向何方呢?
沒過多久,需求發生了變更。小剛和小美的代碼具有充分的柔軟性,可以很優雅的應對變更。
并且沒有引入新的問題。而小明寫的意大利面條式代碼(Spaghetti Code),則由于復雜性提高,而引入了新的上百個Bug。但是由于代碼規模大,所以在原來的考核標準下,小明仍然得到了好評。而小剛和小美則繼續得到中評或者差評,因為他們的工作看起來太簡單了。
很顯然,這個指標已經不能夠正確的反映質量狀況了。那么到底是什么地方出了問題?又應該如何改正呢?
首先,這是個目標和方法背道而馳的指標。
程序員短期之內水平飛速提升的可能性基本上不存在,而作為程序員面臨這個公式的最佳策略是稀釋代碼。下面是程序員的策略圖
所以,選擇稀釋代碼是個最簡單的策略。那么稀釋代碼的最佳策略是什么?復制粘貼
復制粘貼的最大問題是什么?引入更多的bug(請參考DRY原則?)。為了能夠提高質量的最佳策略竟然是引入更多的問題!這就是這個指標帶來的問題之一。
問題之二是,這個指標帶來的隱含意思是,向團隊宣布:我們不歡迎那些程序寫的好的程序員。
就像上例所提到的,寫的好的小剛,和正在努力寫得好的小美都得不到好評。至于那個無稽的
7-10個/千行的指標(這個數字是被廣泛使用的一個數字)更是莫名其妙。這個的潛在意思是“我不相信你能夠寫出來高質量的代碼”。WTF??
問題之三是強湊Bug。當QA團隊也要面臨這個指標考核的時候,他們會怎么做?一個bug拆開寫,同一個原因的bug分開記錄,這樣可以湊到這個指標區間,來粉飾數據。
這些假數據對于決策有什么幫助呢?
同樣的,千行代碼生產率這個指標,也需要放棄。
這背后的最重要的原因就是:
功能的多少和代碼行數不成正比關系,甚至也不呈現正相關關系。
比如,我寫的一套Java代碼框架,允許定義頁面的操作為空白。
比如:
@Controller
@RequestMapping("/books")
public class BookController extends CrudBaseController {}
就可以完成對圖書的增刪改查操作。
增加一組新的功能,只要幾行代碼而已。有的時候增加新功能甚至是需要減少代碼行數的。
所以,凡是以代碼行數來統計什么的指標都是不可靠的。
有人會說,我們的公司不會有人故意稀釋代碼,所以代碼行數在我們這里是可以使用的指標。
這個推論并不成立。因為代碼行數和質量并無任何直接關系。這就好像是扔磚頭看風向一樣。自欺欺人而已。
那么,說了這么多,不這么考核質量,怎么考核質量呢?有幾個常用的可靠指標,推薦給大家
1. 圈復雜度(Cyclomatic Complexity)?
簡單的說圈復雜度越高的代碼會有越多的Bug,這個是業已被證明了的。圈復雜度反應了代碼的耦合度。都要寫低耦合高內聚的代碼,那么這個指標就可以幫助更好地了解代碼的耦合度情況。
推薦的圈復雜度不要超過10,如果實在做不到,那么不要超過20。
如果你的團隊代碼的圈復雜度已經超過100了,你可能需要考慮些大動作了。
測量圈復雜度的工具也有很多。下面推薦幾個:
Source Insight
Code Metrics
Cobertura
2. 平均缺陷修復時間(Mean Time To Repair)?
發生缺陷并不可怕,可怕的是修復的時間過長。假設每個缺陷修復時間只要幾分鐘,那么有幾十個Bug,修復的總計時間也并不會太長。而平均一個Bug修復需要3天的那種(其中2天都在調查問題根源),基本上代碼扔掉重寫的成本都會比在補丁上繼續打補丁的成本要低得多。
平均缺陷修復時間能夠更好地反映代碼本身的質量狀況,以及團隊的成熟程度。
往往平均修復時間較長的代碼都是復雜度高,耦合度高的代碼。而平均修復時間短的代碼都是結構相對清晰,命名規范,容易理解,擴展和變更的代碼。
如果你的公司還在使用“千行代碼缺陷率”,你把這篇文章轉給相關人員看看吧。