🤫 關注 Zilliz 微信公眾號並回復「重構」🤫
獲取《重構:改善既有代碼的設計》超詳細思維導圖
雖然代碼還是可以跑,但是各種規則越來越複雜、核心繼承體系越來越凌亂、系統的維護工作越來越重……
1999 年,Martin Fowler 作為技術顧問造訪了一個項目,他建議項目經理好好整理這些亂糟糟的代碼。然而,項目經理表示:🙏算了吧🙏
六個月後,這個項目宣告失敗,因為代碼太複雜難以調試,性能也達不到要求。
這件事給 Martin 留下很深的印象,隨後,他寫下了《重構:改善既有代碼的設計》。
《重構》出版 22 年後,已成為軟件開發領域不可替代的經典。這本書解釋了重構的原理和最佳實踐方式,並給出了修改代碼的動機和具體案例,值得反覆消化咀嚼。
這本書還凝聚了多位軟件開發領域專家的寶貴經驗:摩根大通架構師 Bill Opdyke 在第 13 章記述他將重構技術應用到商業開發過程中的一些問題;軟件開發方法學泰斗 Kent Beck 和 Don Roberts 合寫了第 14 章,展望重構技術的未來——自動化工具;Kent Beck 還寫了最後一章,總結如何學習重構。
你將從這本書中獲得:
- 理解什麼是重構、為什麼要重構、何時重構,理解
- 理解重構原則:一次一小步地修改代碼並多次測試
- 實操演練重構的動機和方法,使既有代碼更易理解、提升軟件的可維護性
無論你是軟件工程師還是產品經理,都需要翻一翻這本經典;而系統設計師和架構師則更有必要了解重構原理,根據需要在自己的項目中運用重構技術、優化系統性能。
💡 小編提醒,這本書中第一版的案例語言使用 Java,第二版的語言使用 JavaScript。總體而言,作者展示的重構手法在各種主流的面嚮對象語言中基本上都可以通用。
為何重構?
第二章中,作者詳細介紹了重構的價值。重構不僅可以改進軟件設計本身的缺陷、幫助找到 bug、提升開發速度,還可以使軟件更容易被理解——這是因為,程序設計很大程度上是人與計算機、人與人的溝通。
Martin Fowler 曾提及,任何一個傻瓜都能寫出計算機可以理解的代碼,唯有能寫出人類容易理解的代碼的,才是優秀的程序員。
所謂程序設計,便是與計算機交談。你編寫代碼告訴計算機做什麼事情,它的響應則是按照你的指示行動。你得及時填補「想要它做什麼」和「告訴它做什麼」之間的縫隙。這種編程模式的核心就是「準確説出我想要的」。除了計算機之外,你的源碼還有其他讀者。計算機是否多花了幾個小時來編譯,又有什麼關係呢?如果一個程序員花費一週時間來修改某段代碼,那才要命呢——如果他理解了你的代碼,這個修改原本只需一小時。……而很多時候,那個未來的程序員就是我自己。
《重構(第2版)》譯者熊節也曾談到,「編程其實是個社會活動」。
一方面,程序員要把自然語言説出來的需求翻譯成機器能運行的機器語言;另一方面,翻譯出來的結果(也就是代碼)還要支撐團隊(包括技術和非技術的團隊)不斷地在它基礎上協作和交流。……編程的大挑戰不是把代碼寫出來,而是要在代碼的基礎上建立有效的多方溝通。
那麼,我們何時需要重構?書中第三章列舉了一些「代碼的壞氣味」。「壞氣味」指的是代碼中某些不完美之處,開發人員可以通過這些細節上的徵兆在代碼中追捕到更大問題。小編不禁聯想到了《Clean Code》中的「好氣味」和「壞氣味」。
一個重構案例
眾所周知,重構有風險,挖坑需謹慎。如果重構方式不恰當,風險反而更大。
試想一下這樣的情況:你挖掘自己的代碼,很快就發現了一些可以修改的地方,於是你挖得更深。挖得愈深,可以修改的地方就愈多……最後,你給自己挖了一個大坑,再也爬不出去了。
為了避免掉進坑裏,重構必須按照一定的原則和方法進行。
作者在第 5 - 12 章給出了一個重構列表,每一個重構案例都寫明瞭重構適用的情景、動機、重構方法。讓我們來看一個案例吧:
Extract Method(提煉函數)
你有一段代碼可以被組織在一起並獨立出來:
void printOwing(double amount) {
printBanner();
//print details
System.out.println ("name:" + _name);
System.out.println ("amount" + amount);
}
將這段代碼放進一個獨立函數中,並讓函數名稱解釋該函數的用途:
void printOwing(double amount) {
printBanner();
printDetails(amount);
}
void printDetails (double amount) {
System.out.println ("name:" + _name);
System.out.println ("amount" + amount);
}
這樣做的動機:
函數應該簡短而有的良好命名。原因如下:
- 首先,如果每個函數的粒度都很小,那麼函數之間彼此複用的機會就更大;其次,這會使高層函數碼讀起來就像一系列註釋;再者,如果函數都是細粒度,那麼函數的覆寫也會更容易些。
- 如果提煉動作可以強化代碼的清晰度,那就去做,就算函數名稱比提煉出來的代碼還長也無所謂。
重構方法
- 創造一個新函數,以它「做什麼」來命名, 而不是以它「怎樣做」命名
- 將提煉出的代碼從源函數拷貝到新建的目標函數中
- 仔細檢查提煉出的代碼,看看其中是否引用了「作用域限於源函數」的變量(包括局部變量和源函數參數)
- 檢查是否有「僅用於被提煉碼」的臨時變量,如果有,則在目標函數中將它們聲明為臨時變量
- 檢查被提煉碼,看看是否有任何局部變量的值被它改變。如果一個臨時變量值被修改了,看看是否可以將被提煉碼處理為一個查詢,並將結果賦值給相關變量。如果很難這樣做,或如果被修改的變量不止一個,你就不能僅僅將這段代碼原封不動地提煉出來。你可能需要先使用 Split Temporary Variable 方法,然後再嘗試提煉。也可以使用 Replace Temp with Query 將臨時變量消滅掉。
- 將被提煉碼中需要讀取的局部變量,當作參數傳給目標函數
- 處理完所有局部變量之後,進行編譯
- 在源函數中,將被提煉碼替換為「對目標函數的調用」
- 如果你將任何臨時變量移到目標函數中,請檢查它們原本的聲明式是否在被提煉碼的外圍。如果是,現在你可以刪除這些聲明式了
- 編譯,測試
隨後,作者給出了無局部變量、有局部變量、對局部變量再賦值三種範例,手把手解釋如何提煉函數。
更多資源
這本書第 5 - 12 章是一份「重構列表」,有些概念比較抽象。為了更好地理解列表的內容,小編推薦 Refactoring Guru 這個網站,網站上不僅有許多關於重構的實際解釋,還介紹了常用的設計模式和設計原則。這個網站可以幫助你用簡單便捷的方式迅速掌握重構的理念、學習各個設計模式。
想要了解更多詳細內容?關注 Zilliz 微信公眾號並回復書名「重構」
即可獲得小編整理的《重構:改善既有代碼的設計》高清思維導圖。
積累代碼量很重要,
讀書、讀好書也很重要。
「Zilliz 好書推薦」欄目,
旨在與你分享技術成長相關的書籍,
與你一起先把書讀厚,再把書讀薄。
——————————————————————————
Zilliz 以重新定義數據科學為願景,致力於打造一家全球領先的開源技術創新公司,並通過開源和雲原生解決方案為企業解鎖非結構化數據的隱藏價值。
Zilliz 構建了 Milvus 向量數據庫,以加快下一代數據平台的發展。Milvus 數據庫是 LF AI & Data 基金會的畢業項目,能夠管理大量非結構化數據集,在新藥發現、推薦系統、聊天機器人等方面具有廣泛的應用。