每日編譯(Daily Build)是你的好朋友

作者:周思博 (Joel Spolsky)
譯:Paul May 梅普華
Saturday, January 27, 2001
屬於Joel on Software, http://www.joelonsoftware.com


1982年我家人帶了一台很早期的IBM-PC到以色列,當時我們還是跑去倉庫等PC由港口進來。我不知道用了什麼方法,說服老爸買齊完整配備,有台軟碟、128 K記憶體、再加上一台點陣式印表機(印草稿用)和一台兄弟牌印刷品質的菊輪式印表機(列印時的聲音和機關槍一樣,不過更吵)。我想我們把能買的配備幾乎都買齊了:PC-DOS 1.0、75美元的技術參考手冊和完整的BIOS原始碼列表、Macro Assembler、還有能顯示完整80行和小寫字母(!)的高級IBM單色螢幕。全部加起來大概是10,000美元(含荒謬的以色列進口稅)。真是奢侈啊!

「每個人」都知道BASIC是種小孩用的電腦語言,要讓你寫出麵條般糾纏不清的程式,還會讓你的腦袋變成和乳酪一樣都是空洞。所以我們花了600大元去買總共有三片磁片的IBM Pascal。這個編譯器的第一輪編譯要用第一片磁片,第二輪要用第二片,連結器則是在第三片。我寫了一個簡單的"hello, world"程式拿來編譯,用的時間總共是8分鐘。

嗯,這時間蠻長的。我寫了一個批次檔把整個過程自動化,把時間壓到7分半。有快一點,不過當我想寫長一點的程式(比如我的名作:一定會贏我的黑白棋)時,還是得花很長的時間等編譯完成。「沒錯,」有位專業程式師告訴我:「我們通常會在辦公室放塊板子,等待編譯完成時就去做仰臥起坐。寫了幾個月程式之後我就有腹肌了。」

有一天從丹麥傳來了一個叫Compas Pascal的絕妙程式,Philippe Kahn把這隻程式買下來並且改名為Borland Turbo Pascal。Turbo Pascal有點誇張,因為他和IBM Pascal的功能基本上相同,可是連文字編輯器一起只要33K記憶體就可以執行,這實在只能說佩服。更驚人的是一隻小程式只需不到一秒就可編譯完成。這就像一家默默無名的公司推出別克LeSabre的同型車款,可是時速有一百萬英哩而且極為省油,環遊世界一圈用的油還淹不死一隻螞蟻。

突然間我的生產力就提升了許多

我就是在這時候學到REP循環的概念。REP代表「Read, Eval, Print」,是敘述lisp直譯器一直在做的事:它會讀取你的輸入,把它求出來,然後印出結果。下面顯示一個REP循環的範例:我鍵入某些東西,lisp直譯把東西讀進去,求解,然後印出結果。

picture-reploop:

以稍大一點的尺度來看,你寫程式的動作其實是一種放大版的REP循環,是一種名為編輯-編譯-測試的循環。你編輯你的程式,進行編譯,測試,然後看看能不能正常運作。

這裡有個重要的觀察結果,就是寫程式時會一再重複這個循環,所以編輯-編譯-測試的循環進行得愈快,你就愈有生產力,最快時就是能瞬間完成編譯。電腦程式師想擁有真正飛快的硬體,而編譯器開發者會無所不用其極地做出超級快的編輯-編譯-測試循環,這正是電腦科學上正式的原因。Visual Basic會在輸入每行程式時進行字彙和文法分析,所以最後的編輯超級快速。而Visual C++的方法則是提供漸進編譯、預先編譯的檔頭和漸進連結。

不過當你進入擁有多個開發人員和測試人員的大團隊時,又會遇到相同的循環,不過更大更複雜。測試人員找到程式的問題並回報問題。程式師會去修正問題。測試人員要等多久才會拿到修正的程式呢?在某些開發組織中,這種開發-修正-重測的循環要花好幾個星期。表示整個組織的運作完全沒有生產力。要讓整個開發組織運作的更平順,就得專注讓開發-修正-重測的循環更緊湊。

要達到這個目的有個好方法,就是每日編譯。每日編譯是一個自動、每天、完整的編譯動作,把全部原始程式重新編譯一遍。

自動 - 因為你會用cron(在UNIX上)或是Tash Scheduler服務(在Windows上)安排每天在固定的時間編譯程式。

每天 - 更密集也可以。連續編譯更吸引人,不過由於版本管理的問題(待會就會提到)可能做不到。

完整 - 你的程式可能有很多版本。針對不同的語言的版本,不同的作業系統,可能還有分豪華版和入門版。每日編譯必須建立所有的版本。而且必須從頭建立每個檔案,不可以依靠編譯器有潛在問題的漸進重新編譯功能。

下面列出每日編譯眾多好處中的幾項:

  1. 當某個問題修好之後,測試人員可以很快就拿到新版本重測,看看問題是否真的修好了。
  2. 開發人員可以比較放心自己的修改不會破壞到要出貨的1024種版本,不必真的自己準備一套OS/2來測。
  3. 在每日編譯開始前把程式存入版本管理系統的開發人員會比較安心,因為知道自己不會因為放入某些會「破壞(break)」編譯的東西而干擾到別人。所謂破壞編譯就是讓編譯無法進行。這對整個程式團隊來說就等於Windows的藍色當機畫面,當某個程式師忘記把新增的檔案放入版本管理系統時常常出現。在他們的機器上都正常,不過等別人由版本管理系統拿程式出來編譯時,就會遇到連結錯誤,然後什麼事都不能繼續做。
  4. 行銷部門及beta測試者之類的外部人員都必須用到尚未完成的產品,這時候就可以選一個已知相當穩定的版本暫時用一陣子。
  5. 如果有維護一個存放所有每日編譯結果的檔案庫,當你發現很奇怪的新問題又搞不懂原因時,可以利用二分法搜尋過去的檔案,找出問題問題第一次出現的時間。再配合良好的版本管理,或許就能找出哪一些更動造成這個問題。
  6. 當某個測試人員回報一個程式師認為已修正的問題時,測試人員可以說在哪一版看到這個問題。然後程式師可以回頭查查自己什麼時候把修正存入,就知道是否真的修好了。

接下來是實施的方法。你需要一台每日編譯的伺服器,它可能會是你能拿到最快的電腦。然後寫一個腳本命令,由版本管理系統取出所有最新的程式碼(你有在用版本管理系統吧?),然後從頭編譯會出貨的所有版本。如果有安裝程式或設定程式,也要重新編譯。所有會出給客戶的東西都應該由每日編譯程序產生。把每次編譯的結果存在依日期編碼的專屬目錄裡。每天在固定時間執行你的腳本命令。

進階閱讀:

 

這些網頁的內容為表達個人意見。
All contents Copyright © 1999-2006 by Joel Spolsky. All Rights Reserved.