If 也是壞味道嗎#
每個程式語言都有 If-else,難道發明者都挖坑給我們跳?並非如此。如同 Data Class 一樣,不是所有 If 都是壞味道,要看上下文與場景。
If 之所以可能是程式碼異味(Code Smell),主要體現在對「SRP — Single Responsibility Principle(單一職責原則)」的破壞:當一個方法依參數產生兩條以上的邏輯路徑,就代表它做了兩件事。
「衛語句」是個例外:用一個 If 把異常 / 邊界情況先處理掉、立即 return,剩下的正常流程只做一件事。這種 If 通常是利大於弊。
Martin Fowler 在 Refactoring 中也特別提到 If 的難兄難弟:Switch Case。語法不同,本質一樣是在迫使一個方法做多件事。
解決之道#
Uncle Bob 在 Clean Code 中建議:
- 盡可能消滅 Switch Case
- 真消滅不掉的,把它「往下藏到主要邏輯之外」
對付 If 與 Switch Case 的常見手法:
- 改採 State pattern(狀態模式)
- 改採 Strategy pattern
- 至少抽個介面,用多型(Polymorphism)取代分支
但若違反 SRP 情節輕微、範圍很小,導入設計模式反而像「大砲打小鳥」。很多時候 If 只是為了處理「新情況」,這時直接拆成兩個只做一件事的方法就足夠:
- 若方法輸入有兩種可能,分別走不同行為,就拆成兩個方法各自處理一種
重構 If 的兩個範例#
- 第二章「在測試保護下消除重複」:示範用多型 Calculator 取代 If 的過程,原先的主邏輯被簡化成「找對應計算機,回傳結果」
- 下一章「重構出 State pattern」:示範如何在測試保護下,把一連串 If 重構成狀態模式
看到 If 一定要換掉嗎#
不一定。If 的出現未必代表方法做了兩件事。即便真做了兩件事,也有情節輕重之分。如果重構成本太高,或修改後反而更難讀,那就先不動,去做更重要的事情。
反正有測試與 git 雙重保護,花五分鐘試著重構,效果不好就 reset 回來。「人生不能重來,但 git 可以。」
原文出處#
- 原書/iThome:https://ithelp.ithome.com.tw/articles/10265064