摘要:控制語句,到底何錯之有呢?
本文分享自華為雲社區《業務代碼如何才能不再寫出大串的if/else?》,作者: JavaEdge 。
控制結構?沒錯!你最愛的 if、for都是一類壞味道,沒想到吧?自己竟然每天都沉浸在寫壞味道的體驗中。
控制語句,到底何錯之有呢?
嵌套代碼
CR 如下分發我剛寫完的一篇博客的案例:

邏輯很簡單,但有多層縮進,for 循環一層,里面有倆 if ,又多加兩層。若邏輯再復雜點,縮進豈不是像啤酒肚一般越來越大?
為啥代碼會寫成這鬼樣子呢?
因為你在寫流水賬,如機器人般地按需求一步步翻譯成代碼。
代碼邏輯肯定沒錯,但功能實現后,未重新整理代碼。
現在就得消除縮進。
從for循環入手,通常for循環處理集合,而循環里處理的是該集合中的元素。所以,可將循環中的內容提取成方法,只處理一個元素:

這就是一次拆分,分解出來事務 issueArticle 每次只處理一個元素。這就優化了縮進問題:
- issueArticles 只有一層縮進,這才是正常方法應有的樣子。
- 但 issueArticle 還殘留多層縮進,待繼續優化。
if 和 else
issueArticle 里,造成縮進的原因是 if 語句。if 縮進很多時候都是在檢查某先決條件,條件通過時,才能執行后續代碼。
這樣的代碼可使用衛語句(guard clause),即設置單獨檢查條件,不滿足該檢查條件時,方法立刻返回。
以衛語句取代嵌套的條件表達式(Replace Nested Conditional with Guard Clauses)。
重構后的 issueArticle 函數:

如今這就只剩一層縮進,代碼復雜度大大降低,可讀性和可維護性也大大增強。
禁用else
大多數人印象中,if 和 else 幾乎比翼齊飛。
else 可以不寫嗎?
可以!
根據文章信息進行收費:

不用 else,簡單方式就是讓每個邏輯提前返回,類似衛語句:

業務簡單的代碼,這重構還很輕松,但對復雜代碼,就得上多態了。
嵌套、else 語句,都是壞味道,本質上都在追求簡單,因為一段代碼的分支過多,其復雜度就會大幅度增加。
衡量代碼復雜度常用的標准,圈復雜度(Cyclomatic complexity,CC),CC越高,代碼越復雜,理解和維護的成本越高。
在CC判定中,循環和選擇語句占主要地位。CC可使用工具檢查,如Checkstyle,可限制最大的圈復雜度,當圈復雜度大於設定閾值,就報錯。
重復 Switch

實際支付的價格會根據用戶在系統中的用戶級別有所差異,級別越高,折扣越高。
兩個函數里出現了類似的代碼,其中最類似部分就是 switch,都據用戶級別判斷。
這並非僅有的根據用戶級別進行判斷的代碼,各種需區分用戶級別場景都有類似代碼,而這也是一種典型的壞味道:重復switch(Repeated Switch),通常都是因為缺少一個模型。
解決方案:以多態取代條件表達式(Relace Conditional with Polymorphism)。
引入 UserLevel 模型,消除 switch:

前面代碼即可去掉 switch:

switch 其實就是一堆“ if…else” 的簡化寫法,二者等價,所以,這個重構手法,以多態取代的是條件表達式,而不僅是取代 switch。
