之前我曾獨自一人用 TDD (Test Driven Development,中譯為測試驅動開發) 的方式,分別用 Python 和 C++ 各寫了一千多行的小程式,感覺滿好的。最近剛好有機會寫一個新專案,就趁這機會開始第三次的 TDD 練習。和前兩次不同的是,這次要和一位組員合作,以 Java 開發。看來正是測試 TDD 威能的最好時機。
由於我的組員缺乏寫測試程式的經驗,剛好可以用來評估是否能在組內推廣 TDD。雖然我之前有過兩次 TDD 開發經驗,但也只是自己邊看文件邊摸索,經驗仍嫌不足。這次進行 TDD 讓我多花了不少心力查相關資料。但是為了擺脫軟體開發後期的泥沼,現在先下點苦工是值得的。這裡記錄一下過程中的心得。
背景知識
了解 TDD 前,得先知道重構 ( Refactoring ) 和單元測試 ( Unit Testing )。個人大力推薦 Martin Fowler 寫的《重構:改善既有程式的設計 》,可以了解何謂好的程式碼、如何找出該改善的程式碼以及如何改善它。書中列出多種簡單的操作流程,相當淺顯易懂。附帶一提,Martin Fowler 的個人站有許多經典好文,值得細細咀嚼。
TDD 簡介
TDD 是個知難行易的道理。知難,是因為我們很難相信它,到不是因為 TDD 概念很複雜,只要三句話就可以交待完 TDD:
- 先寫簡單的單元測試,並執行它。
- 用最簡單的方法實作需要的功能,讓程式能通過測試。
- 重構程式,並確保重構後的程式仍能通過測試。
實務上,這三條規則蘊含了經年累月的經驗法則。若沒親身體驗過,再怎麼解釋它們帶來的好處,也很難令人信服。這三條規則是環環相扣的,由於有先寫測試,才能安心地重構;由於有重構,才能方便地擴充功能;由於專注於最簡單的實作,省掉 over-design 的時間,才能用更快的速度完成該作的事,並有多餘時間寫測試程式和重構。藉由測試程式,程式設計師可以提高對程式碼的信心;透過重構,程式碼易於修改和重用。注意這裡強調「最簡單」的實作,這正是 TDD 精神所在,簡單的實作易於進行,複雜的考量如程式碼是否能重用、是否易於擴充,都留待第三步再做。專心正是將事做得又快又好的祕訣。
天下沒有白吃的午餐,要做到如上所述的理想世界,必須學許多寫測試程式的技巧。如同平常寫程式有輔助工具、函式庫、設計模式等,測試程式亦有對應的東西要學。舉例來說,產品用的程式需要重構,測試用的程式也需要重構。關鍵在於「treating their tests like first-class citizens. 」。反之若將測試程式視為可有可無的附帶程式,只會陷入惡性循環,改變產品用程式的細節得改變測試用程式,反而變成得改兩倍的程式,以及在兩份程式中除錯。結果變得更糟,並誤認為測試程式是累贅。我剛用 TDD 時就因為沒把測試程式寫成許多小巧的函式,或是沒有寫成正確的檢查方式,造成產品用的程式是對的,卻常在測試程式裡除錯,造成無謂的損耗。
沒有留言:
張貼留言