談“測試驅動的開發”

作者: 王垠  發布時間: 2015-04-15 14:48  閱讀: 2202 次  推薦: 7   原文鏈接   [收藏]  

  現在的很多公司,包括 Google 和我現在的公司 Coverity,都喜歡一種“測試驅動的開發”(test-driven development)。它的原理是,在寫程序的時候同時寫上自動化的“單元測試”(unit test)。在代碼修改之后,這些測試可以批量的被運行,這樣就可以避免不應該出現的錯誤。

  這不是一個壞主意。我在 Kent 的編譯器課程上也使用了很多測試。它們在編譯器的開發中是不可缺少的。編譯器是一種極其精密的程序,微小的改動都可能帶來重大的錯誤。所以編譯器的項目一般都含有大量的測試。

  然而測試的構建,應該是在程序主體已經成形的情況下才能進行。如果程序屬于創造性的設計,主體并未成形,過早的加入測試反而會大幅度的降低開發效率。所以當我給 Google 開發 Python 靜態分析的時候,我幾乎沒有使用任何測試。雖然組里的成員催我寫測試,但是我卻知道那只會降低我的開發效率,因為這個程序在幾個星期的過程中,被我推翻重來了好幾次。要是我一開頭就寫上測試,這些測試就會礙手礙腳,阻礙我大幅度的修改代碼。

  測試的另一個副作用是,它讓很多人對測試有一種盲目的依賴心理。改了程序之后,把測試跑一遍沒出錯,就以為自己的代碼是正確的。可是測試其實并不能保證代碼的正確,即使完全“覆蓋”了也是一樣。覆蓋只是說你的代碼被測試碰到過了,可是它在什么條件下碰到的卻沒法判斷。如果實際的條件跟測試時的條件不同,那么實際運行中仍然會出問題。測試的條件往往是“組合爆炸”的數量級,所以你不可能測試所有的情況。唯一能可靠的方法是使用嚴密的“邏輯推理”,證明它的正確。

  當然我并不是讓你用 ACL2 或者 Coq 這樣的定理證明軟件。雖然它們的邏輯非常嚴密,但是用它們來證明復雜的軟件系統,需要頂尖的程序員和大量的時間。即使如此,由于理論的限制,程序的正確性有可能根本無法證明。所以我這里說的“邏輯推理”,只是局部的,人力的,基本的邏輯推理。

  很多人寫程序只是憑現象來判斷,而不能精密的分析程序的邏輯,所以他們修改程序經常“治標不治本”。如果程序出問題了,他們的辦法是看看哪里錯了,也不怎么理解,就改一下讓它不再出錯,最多再把所有測試跑一遍。或者再加上一些新的測試,以保證這個地方下次不再出問題。

  這種做法的結果是,程序里出現大量的“特殊情況”和“創可貼”。把一個“蟲子”按下去,另一個蟲子又冒出來。忙活來忙活去,最后仍然不能讓程序滿足“所有情況”。其實能夠“滿足所有情況”的程序,往往比能夠“滿足特殊情況”的程序簡單很多。這是一個很奇怪的事情:能做的事越多,代碼量卻越少。也許這就叫做程序的“美”,它跟數學的“美”其實是一回事。

  美的程序不可能從修修補補中來。它必須完美的把握住事物的本質,否則就會有許許多多無法修補的特例。其實程序員跟畫家差不多,畫家如果一天到頭蹲在家里,肯定什么好東西也畫不出來。程序員也一樣,蹲在家里面對電腦,其實很難寫出什么好的代碼。你必須出去觀察事物,尋找“靈感”,而不只是寫代碼。在修改代碼的時候,你必須用“心靈之眼”看見代碼背后所表達的事物。這也是為什么很多高明的程序員不怎么用調試器(debugger)的原因。他們只是用眼睛看著代碼,然后閉上眼,腦海里浮現出其中信息的流動,所以他們經常一動手就能改到正確的地方。

7
3
 
標簽:TDD
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()