在專案中是否不應該用其他語言撰寫工具與測試案例
公司的專案完成了第一期,舉行了一個成員會談,檢視專案過程中遭遇的狀況與可改進的內容。在會談中,我談的主題就是我在《建置風險的故事》中所談的內容。除此之外,我也展示了個人在進行專案時使用的一些小工具與功能測試案例。
我展示這些小工具的目的,是為了說明在整個專案開發過程中,除了正式的工作項目之外,還有很多瑣碎的事務。為了幫助我們處理這些瑣碎的事務,我們應該養成寫一些小工具去完成它們的習慣性,這也是為了讓這些瑣碎的、不在工作項目之內的事,能夠被自動化處理,從而幫助我們達成持續整合(Continue Integration)的目標。
這是基於實務經驗所發展出的一種技巧。在《軟體建構之道》一書中,作者提到當一個程序員要進行一項預估工時約5小時的工作時,他們通常會用4個半小時去寫一個工具,再以這個工具使用半小時去處理那件工作。
不幸的是,議題的焦點很快轉移到了我用的語言上了。因為我並不是使用 Java 語言去寫這些小工具。
我個人認為用什麼語言去寫那些小工具,並不是重點。那些小工具不用交付給客戶,也不影嚮接手人員的後續維護。接手人員不用那些小工具,仍然可以進行維護,只是他要自個手動執行許多動作罷了。那些小工具甚至不會列在專案開發的標準開發流程中。如果真的想納入開發流程,也應該是透過 shell script 的形式來包裝,而不是直接執行。舉 deb 為例,像 deb 會指定用 postinst, prerm 這些指令完成指定的工作。這就是用 shell script 進行標準化的安裝程序。dpkg 只關心你有沒有提供 postinst, prerm 這些工具,而不關心這些工具是 binary execute file, 還是 shell script。
在這種情形下,選擇一個撰碼時間比較短的程式語言來寫小工具,是很合理的。我稍早之前,在《對話Java語言》中也一再強調在不必交付給客戶的地方,儘可能用適當的語言來解決問題
。
在會談中,其他成員說我覺得用 Ruby 寫比較快,是因為我熟 Ruby 。這是個誤解。如果我真的要用我熟悉的程式語言來寫,我將會用 PHP 。我的 PHP 實作經驗超過10年,但接觸 Ruby 不過是這兩年的事。
- Java語言和 Ruby語言,對我來說都不是初學,但熟悉度也僅是在教材範例與練習的程度。
- 這件專案,是我第一個用 Java 語言進行的專案(用在交付客戶的主要項目),同時也是第一個用 Ruby 語言進行的專案(用在功能測試案例)。
- 目前主流的程式語言,都有一套 unit test 工具。這些工具的用法和語法,基本相同。不外就是 setup, test, assert 。只要會用其中一種語言的 unit test 工具,就會用其他語言的 unit test。我不認為閱讀與維護一個使用其他語言撰寫的測試案例會有學習門檻。
對我來說,用 Java 語言寫測試案例,與用 Ruby 語言寫測試案例,它們的比較立足點是相同的: 同樣的 unit test 用法,差不多的語言熟悉度。而我個人比較之後,我的答案是,用 Ruby 撰碼節省許多時間。這不只是我個人的經驗。有人用 Groovy 和 Java 去比較撰寫測試案例的時間,他說 Groovy 省時;有人用 Jyphon 和 Java 去比較撰寫測試案例的時間,他說 Jyphon 省時。這個結果是 Java 語言的結構性限制所致,不令人意外。
雖然 Java 語言的結構性,理論上可以保證交付給客戶的項目,是一個穩健的、強固的項目。但是測試案例並不需要考慮穩健度。因為測試案例的工作很明確,測試案例中的軟體錯誤也必須是可預期的。當測試案例是必要內容,但又不必考慮穩健度之時,撰碼時間應該被列為首要考量。
在是否使用其他工具與語言的爭議中,我們也提到它們會不會影嚮我們開發流程的標準化?關於這個疑慮,我認為影嚮應該低於預期。
我前面說應該用 shell script 包裝,隱藏工具細節,令標準開發流程只關心你有沒有提供這個指令,而不管你這個指令是怎麼達成目的。還有在會談中,我提到我們要定期還原測試平台的環境,以便我們時時檢視我們的安裝程序能否快速將我們的工作項目安裝回去。這不僅僅是指交付給客戶的項目的安裝程序,也應該包括開發環境與測試環境的安裝程序。
例如,在我們的專案中,我們在 build.xml 中設定了一組目標(init),作為開發環境的安裝程序。理想狀況是,一個新進人員被指派接手維護其中一個項目時,他只需要去 Eclipse 官網取得 Eclipse J2EE 安裝包,再自 repository 中取出專案源碼,最後執行 ant init ,就完成了開發環境的建置,可以開始維護工作。不過實際上,我們的作法還缺失了一些環節。例如在某些項目中相依了一個額外的軟體套件、也需要進行資料庫的使用設定。但是 ant init 的動作並不包括該軟體套件的安裝動作與資料庫的使用設定,這就是開發環境安裝程序的失落環節。
當我們的開發工作需要使用某些工具時,我們應該把它們寫進開發環境與測試環境的安裝程序中。我們不必反對開發人員採用其他工具或其他語言來幫助他完成工作。我們應該把焦點放在: 當我導入其他工具幫助我完成開發工作時,我有無將這些工具的安裝動作寫進我的安裝程序中(有時候,當我們遇到把工具的安裝動作寫進安裝程序中的作法太耗時間的場合時,我們也必須抑制我們對某些工具的使用偏好。)。
實現開發環境與測試環境的快速安裝與還原的途徑很多。或許用「安裝程序」並不是最方便的方式。例如微軟的 MSF 方法,可以用 Visual Studio Team System 的工具,把開發與測試環境作成虛擬機影像。新接手人員只要取得虛擬機影像就可以開始維護工作。
就算是把自己綁死在 Java 語言之上,也不能保證我們不會碰到後續人員的維護問題。試想5,6年前用 EJB 框架開發的專案,今天要一個只懂 Spring 框架的人去接手,他就接得起來嗎?一間從以前就用 EJB 進行專案的公司,是否也要以「不利後續維護」,而拒絕導入 Spring 框架呢?在我看來,Java 那一堆框架彼此之間的知識落差之大,一點也不小於學習用 JRuby 或 Groovy 寫測試案例這種事。
不論是語言或框架,說到底都是一種軟體開發工具,而我們總是為了提昇生產力而不斷地更換工具。擔心不利後續維護而拒絕採用更方便的工具,無疑是種削足適履的行為。做好建置環境的管理,才是更為重要的事。
樂多舊回應