時間急迫時的處理方式:
新生方法(sprout method):為原有function 添加新邏輯時,另外寫新的方法,並在原有的方法中呼叫新方法,可方便單獨對新方法做單元測試,並抽換掉新方法驗證添加後是否改變行為。
新生類別(sprout class):如果在原有class 內加新方法無法new instance測試,可另外寫在新的class,以方便針對新方法做單元測試。
外覆方法(wrap method):原method pay 重新命名原有method為dispatchXXX,建立一個與舊method 同名的method為pay,裡面呼叫dispatchXXX以及新加method logXXX,但但需注意命名要清楚。
外覆類別(wrap class):參考裝飾者模式(decorator pattern),但一層一層的外覆類別較為複雜需小心使用。(參考:
修饰模式)
缺點:舊的爛程式沒有被改善且有可能造成重複邏輯的程式碼存在
善用依賴反轉原則,讓程式碼依賴interface 或抽象類別,因為介面不易被更動,當實作內容邏輯調整時不易受影響
使用TDD(測試驅動開發)
為想要測試的class 寫一個Test
讓測試通過
消除重複於新舊程式碼中的邏輯
使用繼承去override method
過度使用繼承可能會造成錯誤的理解,會比較建議需要被override 的方法改成abstract method,這樣任何類別都不會同一方法有多個實作(這樣不會違反Liskvo 替換原則,里氏替換原則就是子類可以擴充套件父類的功能,但不能改變父類原有的功能。)
Liskvo 替換原則:
LSP(Liskov Substitution Principle)Liskvo替換原則
且兩個各自繼承自某父類別的class 若同時需要存在使用就會無法達成,建議抽成config 並把需判別config 的method 搬移到設定中
參數化建構子可解開在建構子中隱藏的依賴物件,在建構子中new 的instance 可改用constructor 傳入,若不想異動其他method,則新增一個不需要傳入此instance的constructor供呼叫即可, 若constructor 太多可組成一個instance 傳入
一個Method 不能同時具備Command & Query ,Command 是指改變物件狀態 但不回傳值.Query 是指有回傳值 但不改變物件狀態
修改方法時可以畫一個影響結構圖,判斷影響了哪些方法需注意:
找出Pinch Point(匯點:是自然封裝邊界, 指使用修改方法的共通處) 在匯點處寫測試的好處是只要寫少數幾個測試就能探測大量其他方法變動的目的
特徵測試:
重構需編寫測試來驗證行為沒有被改變,且確認測試覆蓋了被移轉的程式碼,且正確的連接在系統中
違反單一原則(SRP)有兩種形式:
介面隔離原則(ISP):類別大,但客戶並不會全部使用所有方法,可把特別客戶用的那組方法提取出來,建立一個介面,讓這個大類別implements ,客戶存取時便可改用該介面。有利於資訊隱藏,大類別改變時客戶端也不需重新編譯。
同一時間只作一件事
消除重複:將重複的程式碼提取到父類別,差別的地方用abstract method 由子類別各自實作
消除重複後程式碼會自然地往開放/封閉原則靠攏,開放擴展、封閉修改。
- 面對巨型方法若有開發工具有自動重構可善加運用,否則可最好有測試再做重構,不然就是保守的小塊小塊程式碼進行提取
沒有留言:
張貼留言