Chapter 03
約耳測試:邁向高品質程式碼的12個步驟
2000年8月9日,星期三
你曾聽說過SEMA嗎(*1)?這是一套相當深奧的系統,可以測量軟體團隊的好壞。等一下!不要急著連過去看,我想光是要搞懂那個東西大概就要花上你六年的時間。所以我自己有一套無責任的簡易方法來衡量軟體團隊的品質,這套方法的好處是只要花3分鐘,省下的時間足夠讓你唸一趟醫學院。
約耳測試(Joel Test)
1. 你有使用原始碼控制系統嗎?
2. 你能用一個步驟建出所有結果嗎?
3. 你有進行每日編譯嗎?
4. 你有沒有問題資料庫?
5. 你會先把問題都修好之後,才寫新的程式嗎?
6. 你有一份最新的時程表嗎?
7. 你有寫規格嗎?
8. 程式設計人員有沒有安靜的工作環境?
9. 你有沒有用市面上最好的工具?
10. 你有沒有測試人員?
11. 是否在面試時要求面試的對象試寫程式?
12. 是否進行過走廊使用性測試?
1 詳見www.sei.cmu.edu/sema/welcome.html。(編註:原址已失效,請參考http://www.sei.cmu.edu/measu。)
約耳測試的好處是每個問題都很直覺,只要回答是或否。你不必計算每天寫的程式行數、或是每個重大時點的平均問題數量,只要答「是」就加 1分。約耳測試的缺點是絕對不能用來確保核電廠的安全性。得到 12分是完美, 11分勉強可接受,不過 10分以下(含 10分)就表示問題大了!事實上,大部分軟體組織只拿到 2或3分,而這些組織都岌岌可危,因為微軟隨時都是以12分的水準在運作。
當然,這些並不是決定成敗的唯一因素;特別是當你的優秀團隊盡做些沒人要的產品時(對,沒人要)。另外,也可能有那種「高手」團隊,即使完全不理會這些東西,卻仍能做出改變世界的夢幻軟體。不過,除此之外所有人都一樣,如果你能把這 12件事做好,就能建立一個能穩定交出產品的紀律團隊。
1.你有使用原始碼控制系統嗎?
我使用過一些商用原始檔控制系統( source control packages),也用過免費的 CVS(*2),所以我可以告訴你 CVS相當不錯!如果你沒有原始碼控制系統,一旦需要與程式設計人員合作就相當麻煩了。因為程式設計人員無法知道其他人做了什麼,也無法輕易回復成出錯前的狀態。而且原始碼控制系統還有另一個優點,就是原始碼會被簽出( check out)到每位程式設計人員的硬碟裡。我還沒看過哪個用了原始碼控制的專案會遺失大量程式的。
2 參考wwwcvshome.org/。
2.你能用一個步驟建出所有結果嗎?
我的意思是:從最新的原始碼快照開始,要花多少步驟才能建立出貨用的軟體?好的團隊會有單一個腳本檔,只要執行這個腳本,就會從頭簽出所有檔案、編譯每一行程式、建立執行檔(包含所有不同版本、語言以及#ifdef組合)、製作安裝程式,並且產生最後要用的媒體格式:光碟片、網站下載或是其他各種格式。
如果這個程序不是只有一個步驟,就會容易出錯。另外,當出貨時程緊迫時,修正「最後一個(*3)」問題、製作最終執行檔等過程必須要快速完成。如果程式編譯和安裝檔製作等動作需要20個步驟才能完成,你一定會急瘋了,然後做出一些蠢事。
就是為了這一點,我的前一家公司把原本使用的 WISE換成InstallShield(*4)。因為我們必須透過NT工作排程器,在夜間用腳本自動製作出安裝程式,由於WISE無法透過工作排程器半夜執行,因此就把它丟掉了(親切的WISE員工跟我保證,他們的最新版一定會支援夜間執行)。
3譯註:就好像考試收卷前的心態:再寫最後一題就好!
4譯註:這兩個都是用來製作安裝程式的工具。
3.你有進行每日編譯嗎?
在使用原始碼控制工具時,有時程式設計人員會不慎提交(check in)某些內容而導致編譯失敗。舉例來說,某人新增了一個原始檔,整個程式在他的機器上都能正常編譯,可是卻忘記把新增的原12個步驟始檔加到原始碼控制程式庫中。結果這位仁兄非常健忘且愉快地鎖上機器回家了,導致其他人無法做事,也只好很不爽地回家。
導致編譯失敗是非常糟糕的事情(又經常發生),這時每日編譯就很有幫助了,它能保證不會有漏網之魚。在大型的團隊中,要確保能立即修正編譯失敗的最佳方法就是每天下午(像是午餐時間)重新編譯。大家在午餐前盡可能的提交檔案,等大家用餐完畢編譯也已經完成。若結果顯示正常,很好!大家可以簽出最新版的原始碼繼續工作;如果有問題就將它搞定,而其他人還可以用前一版沒 問題的程式繼續幹活。
Excel團隊有個規定,導致編譯失敗的人必須從此負責重新編譯的動作當作處罰,直到有其他人出錯為止。這能讓大家盡量避免造成編譯失敗,同時也是個讓大家輪流熟悉重新編譯的好方法。在我的文章:「每日編譯是你的好朋友」裡有更多每日編譯的資料(*5)。
4. 你有沒有問題(bug)資料庫?
無論如何,只要你在寫程式時(只有一個人寫也是一樣),沒有一套良好的資料庫列出程式中所有的問題,就一定會產生出品質低劣的程式碼。很多程式設計人員自認能把問題清單記在腦子裡,才怪!我從來沒辦法一次記住超過二或三個問題,而且會在第二天早上,或是趕著出貨時把它們全部忘掉。你一定要正式地記錄問題。
問題資料庫可大可小。一個最簡單有用的問題資料庫必須包含每個問題的下列資料:
• 重現問題的完整步驟。
• 應該看到的行為。
• 實際看到的(有問題的)行為。
• 被指派的負責人。
• 是否已修正。
如果你是因為覺得問題追蹤軟體太複雜才不追蹤問題,請建立五欄的簡單表格,填入上述資料,然後開始使用吧!想要深入瞭解問題追蹤,請參閱「無痛錯誤追蹤」一文(*6)。
5 請參見第10章。
6參見www.joelonsoftware.com/articles/fog0000000029.html。
5.你會先把問題都修好之後,才寫新的程式嗎?
古早第一版的Microsoft Word for Windows被視為「死亡行軍」型的專案。進度一直處在落後的情況。整個團隊的工作時間長得離譜,專案卻一延再延三延,大家都承受無比的壓力。拖了幾年後,那個鬼東西終於上市了,微軟就把整個團隊送到Cancun(墨西哥著名海灘)渡假,然後再坐下來做深度反省。
他們發現產品經理過度堅持要維持「進度」,而程式設計人員只能匆匆經過編碼階段。而且正式的時程並未包含錯誤修正這個階段,於是寫出的程式碼非常糟糕。此外,也沒有人試圖要減少問題數量,而事實剛好相反!有位程式設計人員要寫支程式以計算一行文字的高度,結果他只寫了「return 12;」,並等問題報告出爐指出這個函數功能不對。於是,時程表變成一份等著被轉換成問題的功能列表,事後檢討時則稱之為「無窮錯誤法(Infinite defects methodology)」。
為了修正這個問題,微軟全面採用所謂的「零錯誤作法(Zero defects methodology)」。公司裡很多程式設計人員聽了都不禁竊笑,因為感覺就像是管理階層認為能用行政命令降低錯誤數量一樣。實際上,「零錯誤」是指無論何時都要先修正錯誤才能寫新程式。原因如下:
一般來說,愈晚修正錯誤,修正時所付出的成本(時間及金錢)愈高。舉例來說,當你打錯字或出現編譯器會發現的語法錯誤,就修正只是小事一樁。
若你的程式第一次執行出錯時,應該也能立即改正,因為整個程式還在你腦海裡。如果要為幾天前寫的程式除錯,應該需要回想一陣子吧!不過,當你重讀所寫的程式後,就會記起所有細節,並在適當時間內把問題修好。
若是要為幾個月前寫的程式除錯,那很有可能已經忘掉一大半,要修正簡直難上加難!或許,你正在替別人的程式除錯,而當事人遠在阿盧巴渡假,這時除錯的任務就像科學一樣:你得條理分明、小心翼翼地慢慢來,也無法確定要多久時間才能解決。另外,如果要為已出貨的程式除錯,修正問題的代價就更難以估算了!
這就是要立即修正問題的理由之一,因為這樣做能少花點時間。另一個理由是,寫新程式的時間遠比修正現有錯誤的時間容易估計。舉例來說,如果要你估計寫串列排序的程式需時多久,你應該能估算得相當準確;但假如你的程式在裝了 Internet Explorer 5.5之後有問題,要估計需要多久才能修好,恐怕用猜的都猜不出來,因為你不知道(當然不知道)問題點在哪裡。要找出問題可能就要花上三天,但也可能兩分鐘內解決。
如果時程裡包含很多有待修正的問題,那麼這種時程是不可靠的。假如把已知的錯誤都修好了,剩下的就只有新程式了,那麼時程就會變得非常準確。
把錯誤數量維持在零還有另外一項優點,就是面對競爭時反應可以更快。有些程式設計人員認為這樣做可讓產品隨時推出。一旦競爭者推出某個殺手級新功能來搶客戶時,只要把該功能加上去,即可立即出貨,不必修正累積下來的大量問題。
6.你有一份最新的時程表嗎?
在此要好好的談時程表。如果你的程式對公司非常重要,有太多理由可以說明,預知程式完成時間點有多麼重要。但程式設計人員是出了名的不愛訂定時程,他們會對著業務部門大吼:「該完成的時候就會完成了阿!」
但是問題不可能就這樣算了。業務人員有太多的規劃決策必須遠在程式出貨之前就做好決定,如:功能展示、商展、廣告等,而做決定的唯一方法就是定出時程,並且隨時更新。
擁有時程的另一個重點是,可以強迫自己決定要製作哪些功能,並剔除最不重要的功能,以避免功能過度膨脹(featuritis,又名 scope creep)(*7)。
其實,維護時程表並不困難。可參閱本書第9章,那裡會告訴你如何建立好用時程表的簡單方法。
7 featuritis的定義可參閱www.netmeg.net/jargon/terms/c/creeping_featuritis.html(譯註:原址失效,可以參閱http://en.wikipedia.org/wiki/Feature_creep)。
7.你有寫規格嗎?
寫規格就像是使用牙線:大家都同意這是好事,卻沒有人真的這麼做。
我不知道原因,或許是大多數程式設計人員都討厭寫文件吧!所以當全是程式設計人員的團隊面對問題時,自然傾向用程式碼而非文件來表示。他們寧願跳進去寫程式,死也不願先寫規格。
在設計階段發現問題時,只要改幾行文字就能輕易修正。但等到程式寫出來之後,修正的代價就高多了,代價包含了情感(人們討厭拋棄程式碼)和時間,所以會抗拒修正問題。通常未依據規格製作的軟體,到最後的設計都很糟,而且進度完全無法控制。這似乎就是Netscape所發生的問題。它的前四版一團亂,結果管理階層還愚蠢地決定把程式丟掉重新開始(*8)。然後在Mozilla上又重蹈覆轍,製造出一個無法控制的怪物,耗了好幾年才進入alpha測試階段。
8請參閱第24章。
我的小秘方是把程式設計人員送去上密集的寫作課程(*9),讓他們變得不那麼排斥寫作,就可以解決這個問題。另一個方法是雇用聰明的產品經理來寫規格。不管用哪一種方法,你都應該強制執行「沒有規格就不寫程式」這個簡單的規則。你可以由第 5章到第 8章學到所有關於規格的內容。
9如同耶魯大學的「 Daily Themes」課程( www.yale.edu/engl450b/),以要求學生每天寫一篇短文而聞名(譯註:原址已失效,可以在 http://www.yale.edu/english/undergraduate-courses.html找到相同課程)。
8.程式設計人員有沒有安靜的工作環境?
有大量的文件記載,為知識工作者提供空間安靜及隱私可以提昇產能。軟體管理經典著作《 Peopleware》也詳盡地記載了這種產能上的增益(*10)。
10由Tom DeMarco和Timothy Lister合著,《 Peopleware: Productive Projects and Teams(Second Edition)》(Dorset House Publishing, 1999)(譯註:本書有中文版,《Peopleware:腦力密集產業的人才管理之道,方亞瀾、錢一一譯,經濟新潮社》)。
其中的原理如下。我們都知道知識工作者進入「沉浸狀態」(flow,也稱作 in the zone)時,工作效果是最佳的。這時他們會完全與環境脫離,全心專注在工作上。他們忘記時間並絕對專注地產出極佳成果。他們所有豐富的產出也都是在這個時候完成的。作家、程式設計人員、科學家,甚至是籃球員都會告訴你進入「沉浸」的情形。
問題是要進入沉浸並不是那麼容易。你可以試著計時,平均大概要15分鐘才能開始全速工作。一旦碰到累了或是那一天已經有很多創造性的成果,會根本無法進入沉浸,然後就只能看看網頁、玩玩俄羅斯方塊打混過完一天。
另一個問題就是沉浸不容易維持。噪音、電話、同事的中斷(特別是這一點)都會讓你脫離沉浸。假設有個同事問了一個問題只讓你中斷了一分鐘,實際上,卻會讓你完全脫離沉浸,必須再等半個小時才能回復生產力,導致整體產能都出問題了。如果你身在一個喧鬧的開放辦公環境中(就像某些網路公司最愛的類型),行銷部門在程式設計人員旁一直對著電話大喊,那麼你的產能就像一直被中斷的知識工作者一樣顛簸,永遠無法進入理想的「沉浸」。
這對程式設計人員來說是非常嚴重的事情。生產力的多寡在於能否於短期記憶體中處理大量的細節,而任何一種中斷都會讓這些細節完全消失。等你轉回來工作時,就會完全不記得任何細節(例如,正在使用的區域變數名稱,或是搜尋演算法寫到哪了),必須把剛才寫的東西找出來,於是速度就這樣放慢下來,直到你回復為止。
以下做個簡單的計算。就用剛才的說法:打斷程式設計人員的一分鐘,事實上是耗費了15分鐘的產能。假設有兩個程式設計人員Jeff和Mutt,把他們安排在一個標準呆伯特式牛棚相鄰的開放隔間中。 Mutt忘了strcpy函數的Unicode版本拼法,他可以花30秒自己查出來,也可以花15秒問Jeff。由於對方就坐在旁邊,所以選擇問Jeff,於是Jeff就分心並損失了15分鐘的產能(但替Mutt省了15秒)。
現在把他們搬到兩間有牆有門的獨立房間裡。如果Mutt忘記那個函數的拼法,他可以花30秒查出來,也可以花45秒過去問Jeff(以典型程式設計人員的身材來說,要離開位置並不輕鬆),結果他就自己查了。於是Mutt損失30秒的產能,不過,卻替Jeff省下15分鐘!
9.你有沒有用市面上最好的工具?
用編譯式語言撰寫程式得花一些時間進行編譯,可說是一般家用電腦還無法瞬間完成的事情之一。如果你的編譯過程超過幾秒,去找台最新、最棒的電腦可以替你省點時間;如果編譯需要超過15 秒,程式設計人員覺得無聊就會跑去看線上新聞 The Onion(*11),然後陷在裡面耗掉幾個鐘頭的產能。
11 請參見http://www.theonion.com。
在單螢幕系統上替 GUI程式除錯並非絕不可能,但用起來很痛苦。當你在撰寫GUI程式時,或許使用兩台螢幕會讓你輕鬆許多。
大部分程式設計人員到最後都必須修飾圖示或工具列所用的圖,可是大部分的人都沒有一個好用的圖形編輯器。雖然用微軟的小畫家修圖實在令人不可思議,不過,卻是多數程式設計人員不得不做的事。
在我的前一家公司(*12),系統管理員會一直傳送自動發送的垃圾信給我,抱怨我在伺服器上使用了超過「 220 MB」的硬碟空間。依據現在硬碟的價格,這點空間的費用還遠不及我所用的衛生紙。即使只花10分鐘清理目錄,也是產能的極大浪費。
12參閱第32章。
一流的開發團隊並不會虐待他們的程式設計人員。工具不佳所引起的挫折感雖然很小,累積起來還是會讓程式設計人員心情超級不爽、外加脾氣暴躁。而心情不爽就等於是無生產力。
不過,程式設計人員也是很容易被酷炫、新潮的東西所賄賂,這比用加薪叫他們工作要便宜得多了!
10.你有沒有測試人員?
如果你的團隊沒有專門的測試人員(至少每兩到三個程式設計人員要配一名),就可能會推出問題很多的產品,不然就是浪費錢,像是讓時薪 100美元的程式設計人員去做測試員(時薪 30美元)做的事。省下測試員的錢並不是真正的節省,這是非常明顯的道理,但我實在很驚訝很多人卻還認不清這一點。我們將在第22章中會有更多的討論。