如果你想創建一個只包含一個源程序文件的簡單程序,那么你只需要編譯、連接那一個文件就可以了。如果是一個團隊項目組,有著許多甚至上千個源程序文件,那么要創建一個可執行程序的過程就變得更復雜、更耗時。你必須用各種各樣的組件將程序逐步建立起來。
在微軟或其它一些軟件公司中慣例是:每日構造并做“冒煙測試”。每天都對已完成的源程序進行編譯,然后連接組合成可執行的程序,并做“冒煙測試”,以簡單的檢查該執行程序在運行時是否會“冒煙”。
帶來的好處
雖然這是一個非常簡單的過程,但卻有非常重要的意義:
1、能最小化集成風險
項目組可能遇到的一個很大的風險是,項目組成員根據不同的系統功能各自開發不同的代碼,但是當這些代碼集成為一個系統的時候,也許系統完成不了預期的功能。這種風險的發生取決于項目中的這種不兼容性多久才被發現,由于程序界面已經發生了變化,或者系統的主要部分已經被重新設計和重新實現了,相應的排錯工作將非常困難和耗時。極端情況下,集成的錯誤可能回導致項目被取消掉。每日構造和冒煙測試可以使這種集成錯誤變得非常小,而且便于解決,防止了很多集成問題的產生。
2、能減小產品低質量的風險
這種風險是和集成不成功、集成出錯相關聯的。每天對集成的代碼做一些少量的冒煙測試,即可杜絕項目中那些基本的質量問題。通過這種方式,使系統達到一種周知的良好狀態,維護這樣的系統可以防止系統逐步惡化到耗費大量時間排查質量問題的地步。
3、能簡單化錯誤診斷
當系統每天都進行build和測試時,系統任何一天發生的錯誤都能夠變得十分精細,便于排查。比如在17日系統還運行正常,18日就出錯了,那么只需要檢查這兩次build之間的代碼變化就可以了。
4、能極大鼓舞項目組的士氣
看到產品的不斷成長,能夠極大的鼓舞項目組的士氣,有時甚至不管這個產品到底用來做什么。開發人員可能會為系統顯示了一個矩形而感到激動。通過每日構造,產品每天進步一點點,保證項目士氣的持續高漲。
進行每日構造和冒煙測試
雖然說這是一個簡單枯燥的活,每天進行build,每天進行測試,但也有著一些值得注意的細節:
1、每天堅持
每日構造,最重要的就是“每日”。如Jim McCarthy所說,把每日構造看作是項目的“心跳”,沒有“心跳”的話,項目也就死了(Dynamics of Software Development, Microsoft Press, 1995)。Michael Cusumano and Richard W. Selby描述了另外一種隱含的比喻,把每日構造比作項目的“同步脈沖”(Microsoft Secrets, The Free Press, 1995)。 不同開發人員寫的代碼在他們的“脈沖”之間肯定都會存在“同步”的差異,但是必須有這樣一個“同步脈沖”,使得這些代碼能夠組合為一個整體。當項目組堅持每天把這些不同的“脈沖”組合到一起的時候,開發人員脫離整體的情況就會得到極大程度的杜絕。
有些項目組把這一過程簡化為“每周build一次”。這樣帶來的問題是,某一次build失敗后,可能要回溯好幾周才能找到原因。如果這種情況發生的話,已經得不到經常build帶來的好處了。
2、嚴格檢查每一次build
要保證每一次build的成功,就必須保證build后的結果(也可稱為build)是可以正常運行的,如果build不可運行,那么本次build被認為是不成功的,同時應該將修復此次build的工作提高到項目組最高級別來處理。
對于如何衡量一個build,每一個項目組都會定義一些自己的標準,這些標準需要設定一個嚴格的質量級別來處理那些特別嚴重的缺陷,同時也需要具有一定的伸縮性來忽略掉那些微不足道的缺陷,一些不適當的關心也許會使整個過程舉步為艱。
一個好的build起碼應該具備以下條件:
●能夠成功編譯所有的文件、庫,以及其它相關組件;
●能夠成功鏈接所有的文件、庫,以及其它相關組件;
●不能存在任何使得系統無法運行或者運行出錯的高級別故障;
●當然,必須通過冒煙測試
3、每天進行冒煙測試
冒煙測試應該是對整個系統流程從輸入到輸出的完整測試。測試不必是面面俱到的,但是應該能夠發現系統中較大的問題。冒煙測試應該是足夠充分的,通過了冒煙測試的build就可以認為是經過充分測試、足夠穩定的。
不進行冒煙測試的build是沒有太大價值的。冒煙測試就像一個哨兵,在阻止著產品質量惡化和集成問題的產生,不進行冒煙測試,每日構造可能會變成浪費時間的練習。
冒煙測試必須隨著系統的擴充而擴充。最初,冒煙測試可能是非常簡單的,比如驗證系統是否會打印“Hello World”,隨著系統功能的擴充,冒煙測試需要越來越充分。最初的冒煙測試也許只需要幾秒鐘來執行,逐漸地,測試可能會花費30分鐘,1小時,甚至更長。
4、建立一個專門的build小組
在很多項目組,維護每日構造,并更新冒煙測試用例,會耗費一個人工作的大部分時間。因此在一些大的項目中,這項工作獨立成不止一個人來完成的全職工作。比如在 Windows NT 3.0的研發中,就有一個由四個全職人員組成的專門的build小組(Pascal Zachary, Showstopper!, The Free Press, 1994)。
5、為build增加修訂,如果這樣做有意義的話
一般開發人員不會每天都經常向系統中快速的增加實際的代碼,通常是每隔幾天,他們在開發好完成某個功能的一套代碼以后,然后集成到整個系統中。
6、規定一些導致build失敗的懲罰措施
很多執行每日構造的項目組都會規定一些懲罰措施,來懲罰那些導致build失敗的行為。從最開始,項目組成員就清楚的知道,build的正常執行是項目組的頭等大事。一個失敗的build是項目組的意外,無法成為項目組工作的準則。必須堅持:導致build失敗的同事,必須停下手中的工作,首先來解決build失敗的問題。如果一個項目組的build經常失敗的話,久而久之的,再來談build的正確性就沒有意義了。
有種輕松的懲罰措施,能夠突出解決問題的優先性。Some groups give out lollipops to each "sucker" who breaks the build. This developer then has to tape the sucker to his office door until he fixes the problem. 有些項目組會懲罰犯錯的同事戴上山羊角,或者向一個項目基金捐獻5塊錢。
有些項目組對此的懲罰就有點殘酷了。微軟的開發人員,在一些知名度很高、很重要的產品如Windows NT,Windows 95,Excel等產品后期研發中,被要求隨時帶著尋呼機,如果你的代碼導致build失敗的話,即使是凌晨3點鐘,也會要求你立即來處理這個問題。
7、即使在壓力下也需堅持每日構造和冒煙測試
當項目進度的壓力越來越大時,維護每日構造的工作看起來有些浪費時間,但是恰恰相反。在壓力之下,開發人員丟掉一些平時的規定,會采用一些設計和實現的捷徑,這在平時壓力較小的環境下一般時不會用的。代碼的review和單元測試也可能會比平時粗心一些,這些代碼的狀態變化也會比平時快很多。
為防止這種情況的出現,每日構造會堅持相關的規定,讓壓力下的項目保持在正軌上。代碼仍然每天在不斷變化,但是構造過程使得這種變化每天都可控。
誰能夠從每日構造這種過程中得到好處呢?一些開發人員會抗議說,由于他們的項目太大,每天進行build是沒有實際意義的。但是為什么現在最復雜的軟件項目組卻能夠成功的執行每日構造的制度呢?本文首發時,Windows NT包括了560萬行代碼、分布在4萬個源程序文件中,項目組仍然可以堅持每日構造。