最近更新: 2007-06-20

敏捷方法實務研討會會後筆記3 - 反覆式開發過程

雖然每本敏捷方法的書,都會提到測試驅動開發(TDD) 及反覆式開發過程(或稱迭代式開發) ,然而它們並不是敏捷方法獨有的要素。這兩者都是存在已久的編程實務。XP 並沒有新的觀念,它的觀念與程式設計的歷史一樣老(Kent Beck)。但敏捷方法確實把這兩者發揚光大,讓人們注意到這兩種實務作法所蘊涵的強大威力。

陳教授在會中也一再強調反覆式開發過程。但對陳教授解說的內容,我持有兩點不同看法。雖然當時提問了,奈何時間有限,並沒有足夠的時間討論。

反覆週期太長

首先,反覆式開發過程確實不是敏捷方法獨有的特色。我個人早在十幾年前就已經開始接觸反覆式開發過程。它是「個體導向程式設計技術」 (OOP) 的一部分,那時候我們說「快速雛型法」(施保旭,個體導向技術導引)。「較短的釋出週期」同樣也是個體導向技術實作中的重要內容。當時就提出了「寫一點、測一點」的觀念(敏捷編程個人感想)。連 RUP 都很強調反覆式開發。迭代式開發是 RUP 的核心實踐,而且它遠在 RUP 出現以前就已經存在了(Jacobson,CSDN《程序員》2007年4月刊)。

反覆式開發過程的歷史如此之久,其影嚮早已深入到現代的軟體開發流程中。那麼為什麼大家都以為那是敏捷方法的關鍵要素呢?我個人認為是因敏捷方法大幅縮減反覆週期之故。

陳教授在會中說明反覆式開發過程時,其週期平均以2週為一個反覆期(iteration),2個月為一個釋出期(release)。不過我認為這個週期太長了。這是傳統的反覆式開發週期,基本的 OOP 設計方式或 RUP 的反覆週期差不多就是這麼長。而從我以及其他人以往的開發經驗中,我可以肯定這個反覆週期還是太長了,不足以擁抱變化

敏捷方法則透過密集的溝通行為,一舉將反覆式開發的週期縮短到以「工作天」為單位。正因如此,才使人們注意到反覆式開發過程的爆發力。所以我認為要做到以「工作天」為反覆週期,才是「敏捷的反覆式開發過程」。

我個人的實務經驗可支持以「工作天」為週期的說法,特別是在進行 Web 應用程式開發工作時更是明顯。 Web 應用程式通常將許多功能或服務切成一個個頁面,再由頁面上的輸入元件驅動伺服端元件的方法 (可參考《Delphi for PHP is Not on Rails》中的例子)。舉例而言,當使用者點擊「新增」按鈕時就會切換到新增項目的功能頁面;點擊「刪除」按鈕時就會調用伺服端元件的 delete method。所以我可以今天實現新增功能、明天實現刪除功能、後天實現修改功能。兩、三天就實現一個可以立即上線供使用者使用的故事。按照 OpenSource 軟體專案慣用的版本編號方式 (以 x.y.z 的形式表示版本系統。最小位數 z 通常是指錯誤修正或單元部分功能的釋出),我可以每天 release ,遞增 0.0.1 版。

我們再放眼現在的 Web 2.0 潮流。幾乎每個 Web 2.0 服務都掛個 beta 的圖示,然後每天釋出一些。這其中,採用 Ruby on Rails 開發的網站服務最能展現出「敏捷的反覆式開發過程」的生產力。 Ruby on Rails 的生產力據信比 Java 快 4~5 倍(Bruce A. Tate,超越Java)。如果用 Java 開發時的反覆週期是2週 (10個工作天),那麼 Ruby 做同一件事,反覆週期就是2個工作天了。

《人月神話》中提到,運用高階語言和交談式程式編寫(interactive programming)可以倍數提高生產力。如果採用了合適的高階語言,軟體開發的生產力也許可以提升到五倍(第8章)。Harr 所提供的資料顯示,若以交談式工具來編寫軟體程式,至少會得到兩倍生產力的效果(第12章)(Brooks,人月神話)。動態語言符合這兩個條件。以此推算, Ruby/PHP(基於個人偏好,PHP也要算上) 的生產力高於 Java 5~10倍的說法,早有經驗與數據支持。

User sample 和 test case 分開了

陳教授有一張圖,表示單元測試、反覆期、釋出期的過程。我大略畫一下,如下圖所示:

我當時便提問,為何單元測試和使用者測試分開了?而且也拉長了反覆活動的週期。

陳教授回應因為單元測試是程序員自己針對自己當日的設計內容做的測試。而使用者測試則是小量釋出,取得使用者實際使用經驗的工作。

然而我還是認為在強調使用者參與的敏捷方法中,將這兩者分開是很奇怪的事,而且週期還很長。

首先,程序員的單元測試內容所需的資料樣本,不應該由程序員自己產生,而應由駐廠使用專家提供近乎實際狀況的資料。這在抽象的資訊流層次上,便已經將使用者測試與程序員的單元測試工作合而為一了。接著,當程序員完成一個單元提交時 (commit),也會進行一次案例測試 (通常一個故事內容會使用多個程式單元,故一個案例測試就是這個故事中使用到的程式單元一起運作完成一件使用者操作例子的測試,是一種整合測試)。案例測試也應該由駐廠使用專家依實際使用情形模擬操作,這又在 UI 層次上將使用者測試與案例測試合而為一。似乎沒有理由把使用者測試和單元測試分開。

其次,假使這兩者確實有些微不同,我個人以為使用者測試至少也要放在反覆期的活動圈上,而不是放在釋出期的活動圈上。如果等到釋出期才做使用者測試,那麼使用者的需求變化訊息就不能立即反饋回開發活動,往往拖延了開發時程。

我以 Web 應用軟體開發經驗為證,認為使用者測試應該更貼近開發活動。也許有人會想 Web 那種小玩意的開發經驗不準,企業級應用軟體做不到。但據 Robert Martin 的說法,在開發企業級應用軟體時也應如此:

每兩週,目前的反覆週期結束,而下一個週期開始。在每一次反覆週期結束時,都會對客戶展示目前正常運作的可執行程式,並要求客戶評鑑外觀、感覺及其性能。而客戶會提出新的使用者事例來提供他們的回饋。 Robert C. Martin,敏捷軟體開發-原則、樣式及實務(Agile Software Development:Principles, Patterns, and Practices)

我舉一個普遍的狀況說明。原本我們計劃用80%的時程設計,20%的時程讓使用者驗收。於是程序員按照寫的很完整的規格書埋頭苦幹,當然開發過程很漂亮地按照類別與工作卡的內容漸進實作完成,也對類別單元做了單元測試。然而當交付使用者進行驗收測試時,許多需求落差與變更逐一爆出,於是修改工作一再增加,而軟體收工時程也一延再延。最後結算,實際上花了20%時間設計,80%時間修改。我相信這個經驗很多人都碰過。

因為單單使用反覆式開發方式仍不足以擁抱變化,所以敏捷方法要把使用者拉進來,令開發團隊在反覆期甚至每天的單元測試活動中,便能立即得到使用者反饋的使用經驗訊息。做到這種程度時,以「工作天」為反覆週期的敏捷式反覆開發方式,並不是我誇大其詞的說法。

關於測試與縮短反覆週期的內容,我將在下一篇關於測試驅動開發的會後筆記中討論。

相關文章
樂多舊網址: http://blog.roodo.com/rocksaying/archives/3497379.html