最近手上在處理一個改寫程式的工作,把既有的程式進行模組化,抽出成外部的函數庫。在整理的過程中,重新定義一些溝通使用規則,並且引入單元測試,讓之後的每一次修改都能夠由測試來確保既有功能運作正常。因為對於測試驅動開發的不了解,實作的過程當中吃了不少苦頭,單元測試的引入並沒有預期中的讓我思緒清析,反而讓我常常陷入混亂的狀況。
從前的程式撰寫只需要思考「如何實現功能」,而測試驅動開發則是要求先思考「如何測試功能被實現」,對於剛開始運用這種開發方式的我,花費的精力不是原來的二倍,而是三倍以上。因為想完測試方法後,還要再去思考「如何實現測試方法」。如可在可控制、模擬的環境下實作測試程式,和以往開發直接輸出測試用訊息不同,測試訊息是給開發人員看的,因此是「人工判斷」正確與否。而合格的測試程式,則是想辦法「讓電腦能判斷」,並且輸出「未來的自己看得懂」的訊息。
另一個不同,以往輸出測試訊息的程式碼,是混在主要的程式當中。久而久之,程式的行數會因為許多的測試輸出與測試註解而膨脹,變得較難以閱讀。因此測試程式因該獨立於主要程式之外,並且在輸出成果時被排除在外。因此除了必要的公開方法之外,還需要思考額外需要增加的檢驗方法,好讓測試程式得以觀察是否如預期般的表現。雖然可以利用改變方法的存取識別子或是介面來進行封裝,但是開放「只有測試才需要的公開方法」,至今仍然無法完全適應。
發現其它錯誤時,在測試驅動建議「先增加能捕捉到這個問題」的測試程式,然而自己常常習慣性地直接著手修正,往往修到一半才發現應該撰寫測試,又得還原已經寫好的程式,回頭寫測試。早就不知道自己在這一來一回之間,浪費了多少的時間。
講了許多缺點,但測試驅動給了我一些好處。有些時間精神狀況不佳,連自己都不太清楚自己寫了什麼,但由於寫好的測試把關,不至於讓寫好的功能被被弄亂,而「為了撰寫有功能的測試程式」也逼得我去思考各種可能讓程式錯誤的可能,相對而言程式變得更加穩定。只不過由於花費了大量的時間,會讓人不自覺得焦急起來。還許多一點的時間去熟悉,增加速度吧!
還是會持續使用測試來改變自己累積多年的程式寫作習慣,雖然過程式一定會遇到許多困難。只能不斷告訴自己要有信心,這樣子的付出,在撰寫程式時不斷的換位思考是值得的。接著,就是不斷的練習,直到對它的精熟能夠變成一種本能,期許未來的某一天,對於程式的撰寫能夠再提升好幾個水平。
沒有留言:
張貼留言