/RefactorPractice

重構-改善既有程式的設計Lab 使用C#改寫

Primary LanguageC#

RefactorPractice

重構-改善既有程式的設計Lab

使用C#改寫書上的範例

重構的定義:

不改變外在的行為的前提下,對程式碼做出修正,以改進程式的內部結構。本質上來說,重構就是在程式碼寫好之後改進它的設計

重構的原則:

  • 需要有穩定且堅固的測試機制
  • 以微小步伐修改程式,如果引入錯誤便可以很容易發現
  • 如果覺得比較困難增加新的功能,就先重構後再增加
  • 只有寫出人類容易理解的程式碼,才是優秀的程式員

兩頂帽子 - 重構與增加新功能

  • 增加新功能:不應該修改既有程式碼,只管增加新功能以通過測試
  • 重構:不能增加新功能,只管修改程式結構。只在絕對必要的時刻才修改測試。

為何要重構?

  • 改進軟體設計:一個主要的方向就是消除重複的程式碼
  • 使軟體更容易被理解:提高可讀性。
  • 幫你找到Bug
  • 幫你提高編程速度

何時重構?

  • 三次法則:事不過三,三則重構
  • 增加功能的時候重構
  • 修改錯誤的時候重構
  • Code Review的時候重構

程式碼的壞味道(Bad Smell)

  • 重複的程式碼(Duplicated Code)
  • 過長的函式(Long Method)
  • 過大的類別(Large Class)
  • 過長的參數列(Large Parameter List)
  • 發散式變化(Divergent Change)
  • 散彈式修改(Shotgun Surgery)
  • 依戀情節(Feature Envy)
  • 資料泥團(Data Clump)
  • 基本型別偏執(Primitive Obsession)
  • Switch case
  • 平行繼承體系(Parallel Inheritance Hierarchies)
  • 冗員類別(Lazy Class)
  • 誇大其談未來性(Speculative Generality)
  • 暫時欄位(Temporary Field)
  • 過度耦合的訊息鏈(Message Chains)
  • 中間轉手人(Middle Man)
  • 狎暱關係(inappropriate Intimacy)
  • 異曲同工的類別(Alternative Classes With Different Interfaces)
  • 不完美的程式庫類別(Incomplete Library Class)
  • 純資料類別(Data Class)
  • 被拒絕的遺贈(Refused Bequest)
  • 過多的註釋(Comments)

重構手法

重新組織函式(Composing Methods)

在物件中間搬移特性(Moving Features Between Objects)

重新組織資料(Organizing Data)

簡化條件式(Simplifying Conditional Expressions)

簡化函式呼叫(Making Method Calls Simpler)

處理概括關係(Deal With Generalization)

大型重構(Big Refactoring)

重構的現實

為什麼開發者不願意重構他們程式

  • 不知道如何重構
  • 如果這些利益是需要長時間才能展現的,何必現在付出努力? 長遠看來,當專案收穫這些利益的時候,或許自己已經不在職位上了
  • 程式碼重構是額外的工作,老闆付錢給你,是要你增加新功能
  • 重構可能破壞現有程式

如何重構,在哪裡重構

  • 使用自動化工具來識別哪裡需要重構,以及提供重構的建議

重構以求短期利益

  • 重構帶來的短期利益是讓軟體更好修改、更易維護
  • 長期的願景是程式員或程式開發團隊如何開發並維護自己的軟體

降低重構帶來的額外開銷

  • 目前有一些工具和技術,可以使重構快速而相對無痛的完成
  • 重構雖然需要額外開銷,但可以從在程式開發的其他階段協助降低所需心力即滯怠時間獲得補償
  • 儘管重構開銷太大,但當他成為開發規則的一部分,就不會覺得他費事,反而會覺得是不可或缺。

安全的進行重構

  • 相信自己的編碼能力
  • 相信編譯器會捕捉遺漏的錯誤
  • 相信測試套件能捕捉你和編譯器都遺漏的錯誤
  • 相信程式碼複審(code review)能捕捉你、編譯器、測試套件都遺漏的錯誤

安全重構的侷限性

  • 程式員有可能犯錯
  • 有編譯器無法捕捉的錯誤,特別是與繼承相關的作用域錯誤
  • 無法保證測試套件涵蓋所有可能情況
  • 程式碼複審人員可能無法徹底檢查別人的程式碼

學習重構的技術

  • 隨時挑一個目標:某個程式碼開始發臭,就應該將問題解決掉。你應該朝目標前進,達成後就停止。
  • 沒把握就停下來:你無法證明自己所做的一切還能夠保持程式的原意,就停下來,有改善的成果就發布,沒有的話就撤銷。
  • 學習原路返回:當重構已經失控時,要果斷放棄,回到上一個測試可以通過的程式碼版本。
  • 二重奏:兩人結對重構,你的搭檔會看到與想到你沒發現的東西,當你的夥伴不知道你在重構什麼東西,通常自己也會不知道在重構什麼。在重構之前先與夥伴討論目標與方向,這樣夥伴才能指出你的錯誤。