[上課心得] TDD與持續重構、針對遺留代碼加入單元測試的藝術、Classic TDD by Example

最近把91大的Classic TDD by Example的影片RUN了第二次,想說來留下一點上課心得,以及之前兩堂課TDD與持續重構、針對遺留代碼加入單元測試的藝術。以下內文是這些日子的研究,如有不正確,煩請路過看到的大大具體的電我,我會感恩你。

最近才靜下心來想清楚,整天想要搞微服務、高併發,但是程式不好維護修改,從一個單體的服務要往更遠的地方走必定會遇到很大的障礙,而如果程式好改API切分漂亮,那在特定的點上引入適當的工具應該會變得較容易。

記得幾年前參加過91還有投影片版本的三天課程,從單元測試、整合測試、E2E測試、BDD,看起來超豐富的,但回到工作上想要用起來還是障礙重重。其實寫測試的本質重要的是想出那些”必須”的測試案例,想的時間就花一堆了,不會用工具寫扣慢,根本就不會想去好好執行,只有在特別重要然後容易想得出來的案例或依賴少的情況進行輸出。

所以搭配VIM的極速開發技巧要想辦法學一下,它不難,只是你要有信仰,信仰加上時間會產生力量!沒有啦,就是有些時候東西就在那邊,沒多走幾步路去看看永遠都不知道寶藏就在那邊。事實是市面上的編輯器都蠻強大的,只是大家忽略了它,多使用快速鍵,code template等等,一般人看來會覺得這些奇技淫巧並非寫程式的本質,但在追求”效率”這件事上面,這,就是本質。為了在花費大量時間分析研究過後,能在單位時間內將這些具有優秀價值的服務生產出來,達到劍及履及的效率!

針對遺留代碼加入單元測試的藝術

老實說我學完基本的測試規則在Legacy code重構面前根本出不了力的,殊不知原來還有些技巧及開發的注意事項必須了解。

關於這個可以先看看這支影片 Testing and Refactoring Legacy Code ,對我來說這種招式在日常的開發工作裡根本想不出來,原來只要把一段程式碼seam起來,變成一個方法,然後繼承其類別並對那個方法進行複寫Mock就好了,技巧很簡單,但緣分不到就是不知道。然後反覆的執行這個過程,這段為了撰寫測試所seam起來的方法可能在重構的過程中會神奇消失,然後漸漸把一個人人害怕的祖產轉變成一個有受到(測試)保護的…祖產!

關於static

大家有想過static的成員用了之後會產生依賴,它其實是建議不使用的嗎?

甚至部分用static宣告的類別,如Log跟DateTime經常以static依賴的方式呈現,它們讓程式碼變得不易修改或不易測試,雖然有了前面提到的”seam”技巧可以做到修改,但是我們可以在前期的時候就把可測試性考慮進來,不用static就是一個重點了,但很弔詭的這件事對我來說超級反常識,自以為從static拿到了好處,殊不知拋棄了物件導向,犧牲了更重要的可測試性。

那該怎麼辦?

解決辦法就透過依賴注入的方式來取得原本的方法!什麼這是解決辦法?對,沒錯,很反常識。但這樣你也可以在寫測試的時候去方便的Mock這個方法囉。

這堂課我覺得學到最重要的部分大概是學到部分常識會用的寫法,其實會導致一些問題的,語言所具有的特性不是樣樣都好的,這是一個很重要的突破點。

可參考資料:

Refactoring Legacy Code: STEP BY STEP

Testing and Refactoring Legacy code

TDD與持續重構

這堂課重要觀念多到數不清

分析需求

雖然要把需求徹底解析到非常細節是有困難度的,但身為工程師得要去抑制馬上動手寫扣的衝動,回過頭來了解轉換成程式碼過程中,有哪些需要的資料、參數及驗收情境,藉此可以看清是否有什麼沒想到的盲點。

開發手順

前面的事情考慮清楚之後,接下來思考開發的細節,想想當前的這段的API能不能給下一段的API做使用,而不是以CRUD的角度去考慮,每一段的工作都可以幫助到下一段,具有reuse的價值,這樣才不會因為每一段的開發不連貫,思考的事情也不連貫,導致隱性的效率降低。如果可以的話,考慮的層級看可不可以往細節單一方法去,這個開發手順的思考是很需要培養的。

高內聚低耦合

這是軟體開發中很被要求的一件事,但我一直以來只懂低耦合,甚至以為做了一些降低偶合的動作就自然代表高內聚了,譬如說實行了一些相依於介面的概念、依賴注入的框架、有做到Controller/Service分層就自以為好了。

但實際上高內聚要做的事情,不是把方法全部塞在Controller/Service,而是再回推到各個單純的資料物件裡面,也就是說資料物件不再只是單純的資料,而是一個能夠處理好自己資料的「有行為的物件」,將職責內聚在能夠負責的物件身上,而不是一昧的往Service丟。

恩,又是一個破壞常識的觀念。先寫到這邊,反常識覺得太抽象的話可以找一下feature envy這個關鍵字,他是這樣的程式碼裡常出現的壞味道。

TDD

在不花費過多時間的前提下,把要實做的項目條列出來,並且針對項目制定一定的開發手順,然後就開始進行TDD的紅燈綠燈重構的開發步驟。

過程當中可以先用hard code的方式完成測試案例,再從hard code中整理出real code,所以這種情況下案例的scope其實要盡量的小,保持每一步小小的前進,當然對於實作熟悉的話是可以跳過部分小步進行,只是,把項目切小是最重要也是最需要練習的部分就是了。

Classic TDD by Example

這堂課我覺得跟TDD與持續重構相當接近,但課程中帶到的kata題目其實大到有點誇張,然後有更多的重構步驟跟優化可以研究,重要的是有影片可以不斷欣賞觀看,我這兩次都是邊看邊實作,我會需要再看一次只做筆記而不實作,畢竟題目這麼大,相當於一整天的影片內容,我沒辦法沒事重看阿XD

以上,大概是我在追求開發技藝跟效率所上到的課程,希望之後還可以讓我遇到好老師跟好課程。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *