變,這樣做是可以的。但對於95%的產品而言,是需要不斷變化的。如果一些冗餘程式碼、拙劣的程式碼,存在糟糕的結構和投機性設計,雖然能夠正常執行,但這樣的軟體完全是‘金玉其外,敗絮其中’,常常會帶來更大的潛在的問題。對於一個負責任的程式設計師來講,是不能容忍的。一定要重構,重新最佳化,奪回對程式碼的控制權,千萬不能滋生得過且過的情緒!”
阿捷帶頭鼓起掌來,大家紛紛響應。大民不好意思地咧著嘴笑了。
等大家靜下來,大民接著說:“重構不可避免地會帶來一些問題,我們需要建立一個很好的機制來保證重構的正確性。其中很重要的一個實踐就是單元測試,是TDD。雖然一些簡單的重構可以在沒有單元測試的情形下進行,重構工具與編譯器自身可以提供一定的安全保障,不至於引入一些簡單的人為錯誤,但如果只採用傳統方式對程式碼進行測試,例如使用偵錯程式或執行功能測試,這種測試方法不僅效率低下,而且是乏味的、不值得信賴的。重構時,程式碼比以前對修改更為敏感與脆弱。若要避免不必要的問題,則應新增單元測試放到專案中。這樣可以確保每一小步的重構,都能夠及時發現錯誤。”
“這麼看,似乎透過TDD就可以發現很多Bug了啊!因為開發人員跟我們測試人員是按照同樣的功能驗收條件設計測試用例的。我說的沒錯吧?大民?”阿紫問道。
“還不能這樣說!真正按照TDD的方式進行的軟體開發可以非常有效地預防Bug,但不可能透過TDD再找到Bug。因為TDD裡有一個很重要的概念是‘完工時完工’。意思是說,當開發人員寫完功能程式碼,透過測試時,工作也就做完了。你想啊,當開發人員的程式碼完成的時候,即使所有的測試用例都亮了綠燈,這時隱藏在程式碼中的Bug一個都不會露出馬腳來。即使之前沒透過測試,那也不叫Bug,因為工作還沒做完。”
“嗯,我明白了!所以還需要我們測試人員同步設計功能測試用例,進行功能驗收測試才行。那個階段,發現的問題才能真正稱為Bug。”
第11章 你開車,我導航(5)
大民點了點頭,以示認同。
“我有一個問題,我該為一個功能特性編寫測試用例還是為一個類編寫測試用例?”小寶問道,“因為從我們的程式碼中,我看到UT 測試用例都是類和方法。”
“這個問題很好!我以前也有過類似的困惑。因為關於TDD 的文章都說應該為一個功能特性編寫相應的TestCase。後來看了別人的一個Blog,才明白是怎麼回事。他們在開始開發一個新特性時,先針對特性編寫測試用例,如果發現這個特性無法用測試用例表達,那麼將這個特性細分,直至可以為手上的特性寫出測試用例為止。然後不斷地重構程式碼,不斷地重構測試用例,不斷地依據TDD的思想往下做,最後當產品伴隨測試用例集一起釋出的時候,他們發現經過重構以後的測試用例,就已經是和產品中的類/方法一一對應啦!”
“哦,是這樣。”小寶看上去還是半信半疑。
“我感覺從功能特性開始是最安全最穩妥的方式,這樣不會導致任何設計上重大的失誤,也符合簡單增量設計、不斷重構的XP原則。”大民加上一句,以進一步澄清小寶的迷惑。
“那麼TDD到底該做到什麼程度,就算結束了呢?重構總是無止境的。是透過所有的UT測試用例嗎?”小寶問道。
“很簡單!Clean Code That Works。”大民丟擲來一句英文,看來真的想把大家繞暈才甘心。
“那到底啥意思啊?你還是說中文吧,聽不懂你說的Chnglish。”阿紫打趣道。
“這句話是TDD的目標,Work是指程式碼奏效,也就是必須透過所有的UT測試用例,而Clean是指程式碼很整潔。前者是把事情做對,後者是把事情做好。”
“關於TDD還有什麼疑問嗎?”阿捷用目光掃了一遍,見沒人響應,接著說,“那我們再來討論一下結對程式設計吧。上次我們做Scrum釋出計劃的時候,曾經提到我們缺少一個人,看看能不能從部門內部臨時借調一個人過來,幫幫我們。現在告訴大家的好訊息就是,Charles已經正式批准章浩將從下個月加入我們團隊,進行TD的研發!”阿捷非常興奮。
大民還沒等阿捷說完,就插了一句 :“太好了!章浩跟我是前後腳加入Agile的,開發經驗很豐富,又熟悉Agile OSS的整