為什麼會拾起這本書來研讀呢?一方面是因為近期在專案的更換中發現兩個問題
- 讀懂別人的程式碼不易,特別是在工程複雜的時候
- 自己寫的程式碼能否讓別人輕易讀懂,包括後續的維護是否簡易、擴充套件性是否足夠。
- 寫出讓機器讀懂的程式碼很正常,寫出讓別人輕易讀懂的程式碼,才是優秀的。
手頭上剛好有這麼本書,希望能夠在閱讀和做總結的過程中,能不斷嚴厲要求和規範自己,讓自己的程式碼賞心悅目。得到近期荒廢之後另一個進步。PS,估計目前只簡記心得,後續如果有時間可以另外嘗試分享現實經驗。
《重構——改善既有程式碼的設計》(第二版)
前情,重構程式碼的一些抽象關鍵點
- 重構程式碼的步驟
- 確保有可靠的測試集,保證自己每一處修改可編譯且不會引起新增問題
- 每一步都是粒度最小的改動,commit本地,一旦發現問題,可以最快的找到最後的改動點,避免在多步驟的改動後無法快速定位引起問題的改動點。
- 拆分,注意命名、變數、函式、多型。
- 重構不應該使原有功能面目全非,而是結構化調整。
- 兩頂帽子 —— 新增新功能 & 重構,兩者獨立,但可以經常性交替。經常性地對程式碼進行重構,可以保證程式碼框架足夠清晰,不會因為時間堆積而讓程式碼越來越讓人看不懂。
- 只要想重構,就需要有一套可以自測試的程式碼,來快速發現錯誤、避免錯誤。
- 重構有效的關鍵及協同效應。並且需要自我判斷,是否需要重構。
- 自測試程式碼
- 持續整合
- 重構
- 重構影響效能,那麼就關注在影響效能熱點的小部分程式碼上(10%),讓他發揮最大效用。
如何重構程式碼,什麼程式碼需要重構
- 命名不規範
- 重複的程式碼
- 過長的函式
- 過長的引數列表 —— 引數的減少
- 全域性變數引起的莫名bug & 可變資料 —— 封裝變數
- Fancy Evny —— 策略模式和訪問者模式
- 這裡居然講了24種,包括最後的註釋,但慢慢地,看到中間部分,發現其實簡單的重構方法,自己在平時專案中也有形成這種習慣了。
養成自測試的習慣
- 應該在開始編寫模組的時候就寫自測試程式碼,後續當你改動時,就可以通過這些程式碼保證改動的有效和準確
- 正常路徑的測試,邊界路徑的條件也需要考慮(這個其實在自己的實踐中經常被故意忽略,後續要養好習慣才行,如果你注意到邊界行為,那麼就需要去驗證。)
一些重構的方法(作者的名錄),從動機和做法出發
- 提煉函式
- 行內函數
- 提煉變數(這種在使用表示式較長的時候,可以提煉變數,使程式碼更容易閱讀)
- 內聯變數(當變數本身足夠清楚表達含義時,就不需要提煉變數了)
- 改變函式宣告
- 封裝變數
- 引入引數物件(當多個函式使用了相同的引數時)
- 函式組成類(共同的函式作用範圍,可以簡單理解為當一些方法是有相同的共性的時候,比如提取一些工具類的方法)
- 函式組合成變換(需要派生資訊的時候,enrich something, 當你的輸入會得到一個變化的輸出(同個物件,變化了)
- 拆分階段
封裝
- 封裝記錄,封裝變數、封裝到函式或者類中
- 以物件取代基本型別
- 新增中間人 & 移除中間人 (委託關係是否必要)
- 替換演算法
搬移特性
- 搬移函式、搬移變數
- 搬移語句到函式中 <--> 搬移語句到呼叫者中
- 以函式呼叫取代內聯程式碼
- 合併重複語句
- 拆分迴圈(讓一個迴圈只做一件事情)
- 以管道取代迴圈(Replace Loop with Pipeline)【這個Colletion PipeLine的概念比較少使用到,後面關注】
- 移除死程式碼(如果是團隊協同,那麼就指操作自己部分的程式碼吧!想起了還沒畢業的時候,第一次寫一個業務需求,將別人的程式碼改動得亂糟糟,哈哈哈哈哈)
重新組織資料
- 拆分變數(移除對變數的賦值)
- 欄位改名
- 以查詢取代派生變數(Replace Derived Variable with Query)
- 將引用物件改為值物件 <--> 將值物件改為引用物件
簡化條件邏輯
- 分解條件表示式
- 合併條件表示式
- 以衛語句取代巢狀條件表示式(Replace Nested Conditional with Guard Clauses)
- 以多型取代條件表示式
- 引入特例
- 引入斷言(在目前的實際專案中,很少在應用層使用斷言,一般在單元測試中使用)
重構API
- 將查詢函式和修改函式分離(任何有返回值的函式都應該沒有副作用)
- 函式引數化
- 移除標記引數(感覺是func test(A,B) -- > setA(B)
- 保持物件完整
- 以引數代替查詢 -- 以查詢代替引數
- 移除設定函式(如果不希望引數可以被改變,那就去掉setter吧)
- 以工廠函式取代建構函式
- 以命令取代函式(以函式物件取代函式) -- 以函式取代命令
處理繼承關係
- 函式上移(下移)(子類中有相同的方法,可以移動到父類中)
- 欄位上移(下移)
- 建構函式上移(下移)
- 以子類代替型別碼(移除子類)
- 提煉超類 Extract Superclass
- 摺疊繼承體系(當子類和超類無太大區別)
- 以委託取代子類
- 以委託取代超類
其實好像是本書的目錄結構,加上了一些自己的理解,也方便自己檢視 (有些翻譯很生澀,後續有空再仔細解說) 在記錄總結的過程中,發現其實很多習慣已經在實際專案中使用且注意到了,欣慰。當然後面得更好地讓自己養成習慣才好。
以上。