前言
今天要延續上篇重構實戰案例,在書中稱「沒有測試覆蓋的程式碼即是 Legacy Code」的規則下,我們先透過書中解耦合(coupling)的方法先釐清對象的三項功能,並補上測試,接著進入到討論如何重構讓程式碼變「乾淨」,因此此次讀書會時間不夠沒有深入討論這塊,所以以下是我個人的想法,歡迎大家留言討論任何偶疑惑的點。
回顧程式碼
以下將會有三個重構大點進行詳細步驟說明,閱讀時間約 5 ~ 10 分鐘,如果身邊有機會可以開啟編輯器一起來做做看,實際做過一遍大概花費 15 ~ 30 分鐘,專案在這裡,請切到 dab464 這個 hash 的 commit 然後開始閱讀吧。
—
開始之前先說得打臉的,專案一打開發現前幾天寫的測試 Code 馬上就看不懂了,還好讀書會有其他人分享自己的測試程式,才發現自己上次寫的盲點有以下。
- 問題一:過多自定義的變數值,如 userId、trip1、trip2,不容易理解。
- 問題二:TripServiceUnderTest 做了什麼,這是一個要覆寫一些會有連接 DB 的 method 而實作的 class,但反而增加了測試程式的複雜度。
Beyond Yesterday 先重構一下測試程式
- 條動一:可以透過一些常數變數定義好複用在每個 testcase 中。
- 條動二:移除取代 TripServiceUnderTest 的實作,改為之前單元測試工具知名的 Mockery 套件直接複寫原本 class 的 method。
- 再把單元測試四步驟 Setup、Exercise、Verify、Teardown 標上。
調整完以上三點就變成以下程式了
進入真的回顧程式碼
以下是目前可以測試的主程式碼 TripService,目前有了測試覆蓋,我們可以點開以下圖片,好好思考一下「如果是你會想調整哪裡,想個一兩點」,好了就一起往下討論吧。
小備註:UserSession 、 TripDAO 為對 DB 撈取資料的功能物件
重構思考點一:減少大括號數,思考 if else 是否可以減少
抱歉我記得導讀者有講到一個好的名詞,但我沒記下來 Orz ,我先誤稱它為「防禦性程式」好了,以下看看實作。
重構思考點二:*減少全域變數的使用
全域變數一直是 Legacy Code 的大惡夢,因為它常就是牽扯到許多耦合(coupling)的關鍵原因,要撰寫單元測試前要先把他們 mock 掉,就如以下我們在撰寫測試時條動程式碼產生的這兩個「物件接縫」的「制動點」。
以下是我思考最好的方法,這步真的很歡迎討論 > <
我將全域變數透過 Service 建構時傳入,
小討論:這調動是否危險,會有什麼 bug
讓這個「制動點」改在 constructor 決定,但也代表所有 call TripService 實作的地方都需要調整參數。
接下來把「物件接縫」的「制能點」從 method 改在 constructor 實作,直接看以下內容吧。
再修正一下測試程式,以其中一個 testcase 來象徵就好
原本是透過將 service 的 method 進行 mock,這邊改成再 construct 時替換傳入的兩個物件 UserSession 及 tripDAO,改成使用 Mock Object 來指定回傳內容。
小討論:是否是一個危險的調動?
這個重構同時動到了 主程式碼 及 測試程式!我的回答是是的,這真的很危險,通常我面對這種程式是不敢去調動的,除非有補些微整合測試在外層,會稍微有勇氣一點。
重構思考點三:將程式碼放置到屬於他的模組
這點感謝 Fong 大大在自己的重構範例中寫到,提醒了我這步可以調整,就是以下反白的這段亂亂的程式碼,如果你一開始就有注意到的點,那代表你比我還敏感 ~
這段程式碼是判斷 loggedUser 是否為傳入的 user 的朋友,但這段邏輯卻是在 service 實作,或許我們可以將它移入 user 模組中,之後可以複用。
調整後才可以再,簡化 isFriend 這個變數,或許可以用一個三元運算子就可以把 default 回傳值一起涵蓋了。
最後來個,重構前後比較吧
這是重構前,發現的問題統整是
- if else 可以改成「防禦型程式」,減少大括號的使用數
- 全域變數在 method 中到處使用
- 判斷 isFriend 邏輯可以整理至 User 物件中在不同 service 複用,也減少 service 變數數及邏輯
小結
這算是我第一次針對重構及「我覺得好的程式碼」進行文章發表,希望你還喜歡,也希望能多多與大大們交流,尤其是重構二我一直覺得是一個問題點,我每次都很想改,但又改不太動的點。
也希望之後的讀書會能有更多火花,並堅持繼續以文章形式記錄下來。
如果喜歡我這篇文,可以幫我拍手 1-10 下
如果覺得這文章對你有幫助,可以幫我拍手 10–30 下
如果覺得想支持讀書會重構這主題文章,可以幫我拍手 30–50 讓我知道
也記得 Follow我 陳建宇
更歡迎你在下方留言,我很樂意與你討論聊天或回答問題!
參考資料