前文《放棄“千行代碼缺陷率”吧?》說明了為什么MTTR(平均缺陷修復時間)是個重要的指標。那么如何才能夠縮短MTTR,使得整個工程團隊的價值得到提升呢。今后將會就此話題逐步展開,分解到很多具體的工程實踐上,以期望給諸位提供參考。
一、StackTrace
??? 很多編程語言的運行時,都會提供出錯棧消息,最典型的就是Java的StackTrace。
??? 當Java代碼執行的時候發生了Exception,后臺會生成StackTrace。如果打印出來,就可以明確告知第幾行代碼出現了什么異常,那么就可以直接定位到該問題上。并且迅速解決掉。
?? 發生問題的點不一定是問題的根源點,但是問題的發生點清楚了,尋找根源點也就容易的多。
? StackTrace 有Caused By,可能還會有進一步的Caused By一直到RootCause,只要掌握了快速閱讀StackTrace的技巧,解決此類問題的速度還是可以得到有效的提升的。
?小貼士:我見過太多的程序員有“英語恐懼癥”,因為StackTrace信息都是以英文形式展示的。而程序員由于自身英語能力不行,所以選擇了跳過這段最有價值的信息。所以,程序員們,最起碼看到這里的英文的時候要自己閱讀一下。實在看不明白,也可以搜索一下。
二、Log
?? 代碼的錯誤也不一定就只會以Exception的形式出現。比如計算錯誤,邏輯錯誤,并不表現為系統的異常。
?? 一段電線損壞了怎么定位電線哪里有故障。一個常見的有效辦法是:二分法。
從中間的位置檢查,如果上半段沒有問題,那問題就在下半段。然后依次遞進,直到最后定位問題所在,就可以動手修復了。
同樣的方法可以應用于軟件的Bug定位。
首先,要確保代碼是可以分割的。也就是說,分層,分模塊等解耦合的方法都要用上了。這樣就可以很好地插入檢測點。監測點插入之后可以把代碼運行一下看看,看代碼運行到哪個位置停頓了,或者出錯了,這樣就比較容易的知道代碼是如何被執行的了。
那么為什么不用Debug模式來解決問題呢?
首先,Debug模式需要暫停代碼的執行,這個時候就要來大量記憶代碼運行的位置,各種變量的含義,變量的值(Watch窗口只能看到當前類的變量),代碼執行路徑。如果步驟數太多,比如經歷大量循環的時候要不停的點擊按鈕,造成疲勞感。這個過程是耗費很多時間,而且效果不佳的。
其次,Debug模式往往對于多線程無能力為。因為暫停的時候可能背后的某個線程已經在運行了。或者無法達到和真實情況基本一致的效果。導致Debug失效。
再次,對于回調函數Debug模式的表現也差強人意。
三、提高代碼可讀性和可維護性
當然, 并不是所有的Bug都這么容易的被解決掉,因為想要這樣解決Bug得有一個大的前提,就是代碼的結構非常清晰。如果代碼的結構很混亂,耦合度很高,那么就不要指望什么高效的解決問題的方法了,首先要做的就是解耦代碼。如果解耦實在困難,也許"重寫"是個成本更低,效果更好的方法。
而可維護性指標直接影響了代碼的缺陷修復速度。
高解耦的代碼,在某個模塊出現問題的時候,基本上就只會影響到該模塊,并且根據出錯的業務邏輯,可以直接快速定位到xxx類xxx方法。而且由于方法本身長度不大,會很容易的修復。
如何提高代碼的可讀性和可維護性呢。
1. 遵守編程的幾個基本原則。
??? 單一職責原則?
??? 開放封閉原則?
??? 里氏代換原則?
??? 接口分離原則?
??? 依賴倒置原則?
??? 迪米特法則
??? DRY原則?
2. 使用業已被廣泛證明的了模式
??? 23種設計模式及實例
3. 設立團隊的編碼規范
??? 很多常見的命名規則都是已經成為事實標準了,編碼的時候需要遵照這些事實標準,那么團隊在解決問題的時候就會形成一個共識。比如:getter/setter就是獲取和設置值的;大小寫的寫法;一些術語的用法;等等不一而足。
???? 但是,有些時候,比如關于一個數組的長度,不同的語言就會有不同的用法。
???? 有的叫做length,有的叫做size,有的叫做count。這些就提高一下兼容性吧。
四、建立有效的Bug Fix知識庫
? ? ?? 當解決很多常見的Bug之后,Bug應該如何解決基本上應該都有一定的規律可以掌握了。建立起來如何解決常見Bug的知識庫,不僅僅是對自己,對整個團隊來說,也都是有價值的知識庫。當新人加入的時候,快速融入團隊,解決問題也就不是障礙了。