最近在閑暇之余重(第)溫(一..次)此書, 首先能感受到的, 無論你是新程式員還是老程式員, 這本書都已經不具備太多的可讀性了.
由于本書成書年代久遠, 那個時候軟體行業還不夠發達, 面向物件還沒有被大數人理解, 加之編譯器也非常落后, 設計模式也不深入人心, 所以文中提供的所謂重構的心法, 在當時或許有一些意義. 而今看來, 整書400多頁的文字, 主要的思想就是「抽」, 無論是類, 介面, 方法, 邏輯, 還是引數. 但是為什么會有這么大的篇幅, 其中一半的內容是教你如何在一個IDE功能匱乏的年代, 以一個出錯率更低的順序, 來進行上面所說的多種抽象操作.
當然我去除了大量書中已經沒有任何價值的點后, 總結了如下的一些內容, 應該大多數大家已經在作業實踐中已有體會, 主要還是總結一下, 溫故知新吧.
- 思想方面
- 如果發現加特性很難, 就需要重構
- 重構前需要想想有沒有可靠的測驗機制
- 重構要微小步伐, 容易發現錯誤
- Extract method是最簡單的重構
- 寫出機器認識的代碼容易, 寫出人類容易理解的才是應該的, 最大的影響就是命名
- 做移動重構時, 最好先復制粘貼, 測后再洗掉舊的代碼
- 對于另外物件的switch往往可以通過繼承, 多型來取代
- 三次遇到不合理的, 可能就是重構的時候了
- 重構往往通過加隔離層進行
- 不要過早發布介面
- 性能優化應該基于良好的代碼結構, 性能瓶頸往往只會在很小的代碼片段里
- 每次遇到一個bug, 盡量寫個單元測驗覆寫
- 測驗集中覆寫邊緣case
- 代碼壞味道與手段
- 重復代碼
- 抽方法
- 大函式
- 抽方法, 抽類
- 大類
- 抽類, 抽子類
- 太多引數
- 引數變方法, 抽引數物件
- 加新功能修改多個函式
- 抽子類
- 加新功能需要改很多類
- 挪方法, 挪成員
- 函式過度依賴其他類
- 挪方法, 抽方法
- 同樣的幾個引數到處出現
- 抽引數物件
- 大量同樣的基本型別做引數
- 抽類, 不同運算式可抽進子類
- 很多switch
- 考慮用多型取代
- 子類需平行同時添加
- 先持有對方, 再挪方法, 再挪變數, 再合并
- 沒人用的類
- 做內部類
- 沒太大用處的抽象, 引數, 命名
- 洗掉, 重命名, 行內
- 臨時變數命名模糊
- 抽方法, 抽類
- 訊息鏈過長, 物件轉換過多
- 對同一物件的使用抽方法, 推入訊息鏈消除物件
- 過度代理
- 行內代理
- 注釋太多
- 可能代碼寫的太難懂, 需要重構
- 重復代碼
- 資料
- 臨時變數被賦值多次, 則可以抽成方法
- 有時候需要提取多個臨時變數對邏輯進行解釋, 當然更好的可以再抽成方法
- Java按值傳遞, 本質上是物件的參考按值傳遞
- 移除中間人與隱藏委托是相輔相成的
- 如果類無法更改, 就寫個函式包裝他, 類似于工廠方法?
- 如果不能修改, Adapter模式常常用于擴展方法功能
- 子類修改某些變數的獲取可以通過自封裝, 把變數抽象成函式
- 成員如果不用改變, 就由參考變為值物件, 即immutable物件
- 當業務復雜度變高需要將類之間單向關系改為雙向系結關系, 甚至一對多與多對一的關系
- 雙向系結可能會造成很多僵尸物件, 增加復雜度與空間占用, 所以只有真正需要的時候用, 洗掉可以通過將內部系結查詢轉移為傳參, 再在呼叫的位置進行判斷是否為僵尸物件
- 不要使用Magic Number, 常量即可以優化儲存, 又可讀性高
- 封裝欄位可以控制欄位的讀寫, 稱之為資料隱藏
- 對于回傳集合的函式需要回傳只讀副本, 如果需要修改, 則可另行提供修改方法
- 原始型別替換成類, 有型別欄位的類轉換為多個子類, 或者抽象成策略模式, 從而合理改變資料結構
- 如果子類只有常量, 可以抽成變數放父類, 再添加工廠方法創建, 降低復雜度
- 條件運算式
- 條件運算式很復雜的時候, 可以將條件, 執行代碼進行封裝, 更表意
- 嵌套很深的條件運算式的每個結果都作為回傳值的話, 可以簡化為多個if+return, 類似于swift里面的guard, 或者kotlin里面的?:return, 書里叫衛陳述句(Guard Clauses)
- 嵌套很深的條件運算式可以將范圍大的if反向, 實作提前return
- switch運算式有時候可以通過多型來取代
- 函式呼叫
- 函式最好讀寫分離
- 抽象重復性的函式用以復用
- switch構造可以替換成工廠方法
- 從物件內拿出引數再傳遞給某函式不如直接將物件傳入函式
- 當函式的引數來自另外一個函式時, 也可以刪掉引數, 把函式呼叫挪進去
- 函式引數過多可以同物件替代
- 如果不需要設定就不要提供set方法, 變數都需要為final
- 有時候用拋例外替代回傳錯誤碼, 如果程式無法繼續進行的話
- 如果可以條件邏輯避免Runtime例外, 應不要無腦try/catch
- 繼承關系
- 子類同樣的方法應該向上提, 并將不同的地方抽象為抽象方法分別繼承
- 子類構造復制父類欄位應該通過父類構造, super
- 超類與子類差不多, 就合并
- 邏輯相同, 型別不同可以通過模板函式, 模板類解決
- 不能濫用繼承, 組合代理好過繼承, 但也有特殊, 如果需要使用委托函式所有函式或者大量, 則就需要繼承, 不過這一點在kotlin里面也可以通過by來代理
- 復雜的重構
- 整理復雜的繼承關系, 該抽介面抽介面, 摘出更多深層子類
- 領域與表述分離, 就是UI與邏輯分離
- 程序抽象為物件
- 提煉繼承體系
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/106574.html
標籤:其他
