天天看點

靈活開發“松結對程式設計”實踐之五:代碼檢查篇(大型研發團隊,學習型團隊,139團隊,師徒制度,代碼審查)

松結對和緊結對不一樣,兩個人不是總坐在一起随時發現問題解決問題,而是很短時間地坐在一起。其中在後檢查點發生的主要事情有兩個:一是看結果是否符合需求(做什麼),而是看代碼是否存在問題(怎麼做),後者就是代碼檢查。

代碼檢查(也稱代碼審查Code Inspection)是一種由來已久但是很神秘的東西,最初引入是在一些生命攸關、重大财産相關的軟體開發中,典型的就是SSOS(美國航天飛機的軟體),其每段代碼都交由6個人審閱,方可入庫。成果就是在1989年之前(之後筆者沒有資料),SSOS在太空中失效次數隻有一次。筆者親身參與的代碼審查活動包括某數字電視CA系統的代碼審查(25個程式員隻有1個測試,已用于CCTV)、某電信計費系統的代碼審查(一周發現2400個缺陷)、某電信運維系統的審查(2天發現200個重要缺陷,其中1個已困擾團隊5年)、某航空無損檢測系統的代碼審查(傳遞後一年内客戶隻發生一次失效)。

代碼檢查的基本原理就是相信人腦(而非人眼)是判斷代碼好壞的最好工具,比如如果代碼中有一行:if (i == 1001) return die()的錯誤或非法代碼,幾乎無法經由測試包括自動測試發現,但肉眼卻一目了然。

筆者曾編寫過一個“複雜而徹底”的代碼檢查教育訓練教材,但後來發現過于複雜而且還不徹底,是以作罷。下面将要介紹的是一種業餘但卻有效的代碼審查方法。

-----------------------------------------------------------------------

程式員的品質觀

有人曾把程式員分為四級:編寫可用軟體(大緻是大學在校生的狀态),編寫可靠軟體(大緻是好一些的職業程式員的狀态),編寫精美軟體(在簡單性/可維護性/可複用性上有所突破),編寫思想深邃軟體(設計模式、MVC、JQuery及早期OLE、RPC等創始者所做的事情)。

但在現實中,卻往往發現很多程式員停留在第一層次:“你測吧,測出缺陷來我改”“這個不用改也能運作”“這麼編就是難讀點而已”,師徒間的代碼檢查,就是把程式員從第一級别向上提高的過程。

第一段提到的25個程式員+1個測試人員的團隊是01年我們所在的團隊,當時保持了良好的品質風氣。尤其由于大家知道沒有測試人員擦屁股,留下缺陷相當于給自己找麻煩,是以大家不得不習慣自己動手防患于未然。這個産品後來發展勢頭很好,07年曾占據市場60%(之後不詳)。

怎樣檢查

“高手本來自己就要開發很多代碼,還要替新手檢查代碼,多花費時間啊……”這是一個常見問題,答案是:“每天,在後檢查點,花費不超過15分鐘時間,能看出什麼來就說什麼,時間到了就停。”

一般而言,大緻每天高手能編寫100多行有效代碼(按分号計數),新手會多一些但也不超過200(他們編寫代碼比較費),也就是10個螢幕以内。有經驗的人一定知道:高手看新手的軟體,5秒鐘就能發現問題。

常存在的一種情況是高手“看不懂”新手的代碼,當然不是因為技術太精妙了,而是寫得太亂了。但在松結對程式設計裡邊不存在,由于師傅徒弟天天在一起,這200行代碼可謂一目十行,如果以往一直每天檢查代碼,那麼裡邊存在的問題應該不會很多。

檢查什麼

這個是重點,整體包括:

1. 結構問題

代碼最大的問題,不是一兩個地方有技術缺陷,也不是業務邏輯錯誤,而是整個軟體編寫的不好。前兩者都可以通過測試或使用來發現和更正,但後者就不同了。如果回想一下自己見過的各種爛攤子,是不是有同感?具體哪裡有問題怎麼改說不上來,就是整個軟體看上去混亂無章,無從下手。

具體結構問題包括:重複拷貝代碼(不封裝函數,不用Template/泛型……),函數過長(超過一螢幕就叫過長),錯誤封裝(不恰當的public/不用Interface/不内聚/強耦合/在類中封裝了無關方法……),内容錯誤(多個無關類置于一個檔案/不恰當的命名……)等等。

改正結構問題,是從編寫可靠軟體向編寫精美軟體邁進的重要方法。

(筆者部落格中已經寫了幾個“編碼簡單性”的文章可供參考)

2. 業務邏輯問題

就是軟體是否與需求的要求符合的問題。師傅和徒弟經常對業務需求的了解有差異,借此機會同步一下,必要時引入PO(産品經理/策劃人員……)。

有人會說業務邏輯問題不是一測試就知道了嗎?可是測試一般發生在很久以後,有些邏輯測試還需要一定的觸發條件,而且測試隻會發現失效(failure, 與預期不符)而不能發現缺陷(defect, 具體哪裡出了錯),等積累長了,誰也找不到原因了。

3. 程式設計素養問題

很多問題屬于那種“這樣也行那樣也行”的狀态,比如命名/初始值/縮進/斷行……但是高手的做法總是比新手好一些。

比如bool result = true; 這句話就有問題,剛初始化就先宣布成功,必有隐患。這是一個真實案例,而下面也的确有一個分支錯誤地傳回了這個true(實際案例是個HRESULT)。而發現這個問題,不是測試而是代碼檢查。實際上測試幾乎發現不了這些問題,比如上面那段代碼會在某檔案打不開的時候錯誤地傳回這個true,而在測試中幾乎不會故事破壞那個檔案來測試其結果。

實際使用時,不用拉太長的清單,師傅能想到的看到的告訴徒弟就行。

徒弟不需要學到天上去,隻要能學到師傅那麼好就可以了。之前在做CMMI咨詢的時候我弄過一些檢查表,推廣均以失敗而告終。那些表都是為了頂級安全性的軟體考慮的,在普通項目裡邊使用是個災難。

幾個問題

1. 師傅天天檢查,會不會很累?

檢查不全是為了發現缺陷,而是為了提高成長。如果總是發現重複問題,此徒不可教。好學的徒弟有半年時間就能接近師傅了,考慮到師傅一般比徒弟多工作2年,我們是以讓一個人加速1.5年。

2. 不會餓死師傅嗎?

會,也不會。如果師傅止步不前,即使他不教别人,也遲早被人超越;師傅也是需要學習的。事實是會教徒弟的師傅才會學習,而會學習的師傅才會教徒弟。

3. 師傅跟誰學?

師徒制度是最底層團隊制度(1個師傅+1~3個徒弟左右),其上還有更大的結構和更高的高手。我們之前曾把人員層次設為需指導的(徒弟)/可免于指導的(也是徒弟)/可提供指導的(師傅)/可教育訓練的(團隊最進階别的高手),最後一級需要定期與大家分享内容。

師傅作為進階技術人員,還享有機會外出教育訓練/采購圖書等待遇。

師傅自學也很重要,經驗更是不可取代的。前事不忘後事之師,要把自己的經曆和别人的經曆都當作經驗來看待。

4. 師傅努力編好自己的軟體不久已經有很大貢獻了,為何要幫助徒弟?

軟體整體是一個串聯系統,一個環節出了問題整個軟體崩潰(Web軟體好一些)。是以軟體品質取決于最差的部分,而不是最好的部分。

代碼審查的确會占用時間導緻最好的部分變差,但卻使最差的地方變得好得多,整體品質是以而得以提高。

------------------------------------------------------------

從工作層面講,代碼檢查使得代碼的品質尤其是結構品質,整體上保持在師傅可能達到的水準,進而保證了項目的成功。

從學習層面講,代碼檢查使得徒弟可以不斷/漸進地學習,進而花費遠遠低于師傅的時間成本達到更高層次。

心态是其中的關鍵。徒弟不能是以而覺得有一個後盾了可以放任存在問題等師傅發現,要珍惜師傅的時間,也要利用師傅的時間每次都學不同的内容;師傅也不能覺得徒弟學會了對自己是個威脅,威脅時刻都在,不來自于自己的徒弟,也會來自于别人的徒弟,唯有自我提高。

至此所有實踐層面的内容基本上都寫完了,下一篇将提到一些“139團隊”的問題,所謂“139團隊”就是一個使用松結對程式設計工作方式的大型團隊。