重構
關於小步快跑
- 時間緊,少做
- 時間充裕,多做
- 發現問題可以退回上一版本,因為有版控
重構步驟:採用一步一步,逐漸小修改向大修改深化,分解大函數在類別內部進行小修改,拆大物件在不動用原有程式下,進行類別之間修改,在原有程式碼基礎提高程式複用率。
關於程式碼重複與DRY原則
這個章節主要講的是關於DRY原則,當遇到Copy Parse第二次時候,就要遵守DRY原則【不要重複自己原則】。
例如:程式設計師很常用Copy Parse原則,會忽略停下來思考,多培養遇到同樣程式碼,先停下來思考,如何放置對的類別職責中。
比較常見的相近幾種狀況:
- 處理同一個流程,某個環節不同方式。
- 在不同業務中某個功能相似或相近的環節。
- 本身相似與相近的功能。
處理同一個流程,某個環節不同方式
最常見的電商系統在訂單頁面有不同付款方式:信用卡付款、ATM付款、匯款等,最終付款結果是一樣,付款流程不同,重構這些程式碼,將最終付款結果合併一個類別或方法,將不同付款流程抽象為一個介面下和多個實作類別,如信用卡付款實作、ATM付款實作、匯款實作類別等等。
在不同業務中某個功能相似或相近的環節
應付單、付款單、收款單,都有各自不同功能,但他們有相似的環節,例如操作的前的檢驗。
EX:輸入資料的是否合法、檢查帳號餘額等等、檢查使用者是否合法,將這些Code提取出來,進行抽象、合併、讓各個功能呼叫提高程式碼複用。
本身相似與相近的功能
ERP中的應收帳款單據和應付帳款單據,除了借貸方互換,其他地方很雷同或前面提到正常開發票與非正常開發票,可整理原有程式碼將相同程式碼抽離父類別或公用類別,不同的則保持原類別中。
提高程式碼重複使用方法
- 當重複程式碼存在同一個物件時候進行-抽取方法
- 當重複程式碼存在不同物件的時候進行-抽取類別
- 當不同物件複用程式碼的另一種方法-封裝實體類別
- 當程式碼所在類別具有某種並列關係-抽取父類別
- 當出現繼承氾濫時-將繼承轉換為組合
- 當重複程式被割裂碎片時-繼承結合樣板方法模式
當重複程式碼存在同一個物件時候進行-抽取方法
當遇到被比較兩份或多份程式碼放同一個物件中,可提取方法,讓其他程式來呼叫。
當重複程式碼存在不同物件的時候進行-抽取類別
當遇到被比較兩份或多份程式碼不在同一個物件中,可提取類別。
當遇到【散彈槍式修改】(Shotgun Surgery):當遇到一個需求變更分散各處程式碼需要修改,可統一一個工具類別,需求變更就只要針對這個工具類別上調整。
當不同物件複用程式碼的另一種方法-封裝實體類別
當遇到重複程式碼分散原程式的多個程式碼片段中,內部存在較強業務相關性,可將這些程式來提取並封裝成實體類別,該實體類別體現出這種業務相關性。
前一種手法,工具類別是一堆方法集合,實體類別則體現出一定的業務邏輯並使用時產生實體。
當程式碼所在類別具有某種並列關係-抽取父類別
先整理原有程式去比較,將需要重構多份原程式的相同與不相同程式整理出來,在不同程式碼當中維持原程式中,相同程式碼抽離出來可成為獨立的函數,這些就是抽象、合併、復用,進一步抽取父類。
上述這樣演進設計好處,程式共同部分變更,改父類別,各自程式部分變更改子類別。
當出現繼承氾濫時-將繼承轉換為組合
遇到軟體系統複雜時候,使用繼承容易繼承氾濫問題,可以轉換成組合。
步驟如下:
- 完成程式碼的比較
- 將程式碼不同部分封裝統一介面下多個實作類別中
- 將相同部分合併成業務類別讓各個客戶程式使用
例子:ERP系統不同單據產生財務憑證,不同單據產生財務憑證不一樣,應付單據在對方來說是借方科目,將應付科目為貸方;付款單應當將期付款科目,借方科目,結算方式其結算科目為貸方科目…不論何種單據,科目和規則不一樣都是由一到多個借方分錄或一到多個貸方分錄所組成。
原程式分別有不曾單據製作憑證產生類別,應付單憑證產生類別、付款單憑證類別等等,出現大量重複程式碼,開始進行重構,在分析過程,不同單據整個過程,差異產生分錄規則不一樣,合併分錄策略也不相同,但分類產生與合併分錄之間是一種排列組合關係,任一單據可能有三種合併方式。
不同屬性排列組成,容易造成繼承的氾濫。
從上圖設計來看,來一個業務要求用多張應付單按照憑證類型合併方式產生憑證,則使用【應付單實作類別】與按【憑證類型合併】;當另一個用付款單不合併產生憑證時,則使用【付款單實作類別】與【不合併憑證】,功能得以實現。
採用該手法重構有效解決複雜環境的【繼承氾濫】同時提高系統可維護性。
若新增一個新單據則寫它的【分錄產生】實作類別即可。
後續一堆單據例如【應付單憑證產生類別】、【付款單憑證產生類別】,一個【簡單憑證產生業務類別】統統搞定。
當程式碼被割裂成碎片時-繼承結合樣板方法模式
有一種常見狀況是重構程式碼相同部分與不相同部分切割成很多碎片,遇到這情境採用【繼承結合樣板方法模式】。
樣板方法模式:一個演算法定義一系列步驟,並且予許子類別來實現其中一個或多個步驟實作,就可以採用這模式。
情境:該手法將把支離破碎過程,分解成數個方法定義這些樣板方法模式中的父類別中(每個方法是一個步驟),父類別中定義那些方法執行次序。
將程式碼相同寫在父類別,不同部分在子類別中實作。
文中有提到一個例子,作者有提到他經常建立工廠類別,工廠類別都有各自不同但所有工廠類別是一樣狀況
- 採用各種方式(相對路徑、絕對路徑、JAR包或是、ZIP包路徑找尋XML設定檔)
- 讀取XML檔案
- 解析XML檔案
- 根據內容建立產品
- 將產品放入工廠中
- 客戶程式搜尋工廠產品
這其中1、2、5步驟對任何工廠相同,3、4、6步驟則是各個工廠不盡相同。
建立AbstractFactoryTemplate的樣板類別,讓各個工廠繼承它,每個工廠類別實作、3、4、6。
重複程式碼檢查工具
重複程式碼幾乎隱藏在軟體系統所有角落,採用人工方式非常耗時又沒效率,可以採用靜態程式碼檢查工具來完成這項工作。
在開發過程中建立持續整合環境,常常是保證程式碼品質重要手段。
步驟如下:
- 建立版控、並要求PG頻繁提交自己程式碼
- 再版控伺服器上建立持續整合伺服器,如Jenkins
- 在建立持續整合伺服器過程中加入靜態程式碼檢查工具
- 靜態程式碼檢查工具來檢查程式碼是否符合編寫規範,其中一項檢查是否有重複程式碼
將程式碼提交版控後,持續整合伺服器定義尋找新提交程式並下載進行編譯與發佈,在編譯或發布前進行程式規範檢查,在檢查過程中發現有重複程式碼會在發現問題中的一項,以報告方式提交相關人員,並指出程式碼重複位置。
主要合理利用這些工具來讓重構工作更有效率。
筆者覺得這邊比較白話好懂,去尋找工具來嘗試看看,覺得這一篇可以嘗試看看。
https://blog.yowko.com/visual-studio-code-clone/
元哥的筆記