工程師必知的代碼重構指南

作者 | CATE LAWRENCE

譯者 | 冬雨

策劃 | 蔡芳芳

本指南將帶你瞭解進行代碼重構的好處、可能遇到的挑戰、可以採用的工具和最佳實踐,以及重構和技術債務之間的區別。

我們都在尋找清理代碼、降低複雜性和改進功能的方法,重構就是其中之一。

本指南將涵蓋以下主題:

  • 重構是什麼?

  • 重構的好處是什麼?

  • 技術債務與重構

  • 重構度量

  • 代碼重構的示例

  • 代碼重構的工具

  • 重構和對技術經理的挑戰

  • 高級管理層對重構的支持

  • 團隊支持和重構:衝刺還是馬拉松?

  • 文檔和重構

 

01

什麼是重構

關於重構,Martin Fowler 寫過兩本的書,按照他的說法:

“重構是改變軟件系統的過程,這一過程改變的不是代碼的外部行爲,而是其內部結構。這是一種清理代碼、儘可能降低引入 bug 機率的方法。從本質上說,進行重構時,是你在代碼編寫之後改進設計。”

 

02

重構的好處是什麼?

 

重構代碼有許多好處。它將混亂、不正確和 / 或重複的代碼變成整潔的代碼。當多個開發人員貢獻他們自己的代碼時,可能會出現標準化的問題,它正可以解決這一問題。重構可帶來更好的可讀性,並改善源代碼的可維護性以及整體的結構和功能。重構可以使代碼更易於擴展和添加新的特性。刪除不必要的部分(如重複的部分),也可以使代碼使用的內存更少、執行的速度更快。

例如,在 2014 年,Kickstarter 工程師面臨着一項挑戰,隨着用戶數量呈指數增長,導致查詢性能急劇下降。爲了應對此問題,他們重構了一個 MySQL 到 Redis 的查詢,減少了典型的 100ms 以上的加載時間,從而減少了加載時間的方差,總體上提升了網站的速度。

 

03

技術債務與重構

 

 

圖片

 

簡單來說,重構是一種消除或減少技術債務的方法。重構對於維護長期的代碼質量、安全性和性能至關重要。如果沒有定期進行重構,開發商將揹負鉅額技術債務。如果不斷地錯過代碼重構的時機,這種債務也會不斷地增加,從而使新的開發越來越困難,特別是在遺留代碼上的開發。

https://www.stepsize.com/blog/complete-guide-to-technical-debt

 

04

重構度量

使用指標可以讓你對真正需要處理的代碼進行優先級排序。它能防止你試圖一次做所有的事情,讓你先專注於最重要的任務。

此外,你需要度量標準來證明代碼重構的有效性——這不僅僅是關於更改低效代碼的,而是關於更改低效代碼以增加價值的。要獲得真正的價值,你需要單元測試 (例如失敗的單元測試數量) 和功能測試。其他度量包括髮現更少的 bug 和降低圈複雜度——重構的目標應該是降低複雜度。高度複雜的方法或函數 (例如超過 350 行) 是很好的重構目標。

在工作流程和任務方面,也應考慮如何讓重構適應更廣泛的團隊目標或里程碑。其中,應該包括更小的代碼大小和更容易理解的代碼。

 

05

代碼重構的示例

 

代碼重構的例子有很多,本文受篇幅所限,只關注其中的幾個:

紅、綠、重構

重構與單元測試有着緊密的聯繫。最常見的一種形式是測試驅動開發 (TDD),現在一提到敏捷方法就會提到它。它是指在編寫代碼之前先編寫測試。本質上,測試應該驅動編程,說明代碼應該做什麼。

紅、綠、重構是一種 TDD 實例:

—紅色:寫一個沒有實現代碼的測試套件,確保它失敗。

—綠色:編寫實現代碼,讓那個測試套件通過。

—重構:尋找優化和改進代碼的方法。

 

提取方法

https://refactoring.com/catalog/extractFunction.html

將一段代碼從一個現有的方法移動到一個新方法中,新方法的命名要能清楚解釋其功能。這種技術有助於降低代碼的複雜性和提高代碼的可讀性。

 

提取變量

https://refactoring.com/catalog/extractVariable.html

如果遇到難以理解的表達式,或者表達式在代碼的多個地方重複,那麼提取變量的重構方法可以將這樣一個表達式結果或其部分結果放置到一個單獨的變量中,這樣的變量不那麼複雜,也更容易理解。這可以減少複雜性和代碼重複。

 

抽象分支

https://www.martinfowler.com/bliki/BranchByAbstraction.html

抽象分支是爲了以漸進的方式對軟件系統進行大規模的變更,使你可以在變更的同時定期發佈系統。這消除了在分支上重構代碼的複雜性,否則當你試圖合併代碼時,可能會出現問題。

 

組合方法

https://scrutinizer-ci.com/docs/refactorings/compose-method

過長的代碼很難理解,也很難更改。組合方法指的是一系列可用於簡化方法和刪除重複代碼的措施。這包括內聯方法、內聯臨時變量、用查詢替換臨時變量、拆分臨時變量和消除對參數的賦值。

用查詢替換臨時變量示例:原代碼:

const basePrice = this._quantity this._itemPrice;if (basePrice > 1000) return basePrice 0.95;else return basePrice 0.98;

重構爲:

get basePrice() {this._quantitythis._itemPrice;}...if (this.basePrice > 1000) return this.basePrice 0.95;else return this.basePrice 0.98

拆分臨時變量代碼示例:原代碼:

let temp = 2 (height + width);console.log(temp);temp = height width;console.log(temp);

重構爲:

const perimeter = 2 (height + width);console.log(perimeter);const area = height width;console.log(area);

 

06

代碼重構的工具

 

你是否需要專門的工具來進行重構?Martin Fowler 說,自動化工具會有所幫助,但不是必需的。他指出:許多語言的 IDE 都有自動化完成許多常見重構的功能。它們是我的工具包中非常有價值的一些工具,它們可以讓我更快地進行重構。但這些工具不是必需的——我經常在沒有工具支持的情況下使用編程語言工作,在這種情況下,我依賴於採取更小的步進,並使用頻繁的測試來發現錯誤。”許多開發環境自動化了那些機械化的重構操作。主要的代碼重構工具有:

  • Visual studio intellicode

  • Eclipse IDE

  • Spring Tool Suite 4

  • Rider

  • IntelliJ IDEA

  • SonarQube

 

07

重構和對工程經理的挑戰

有些問題會導致需要重構,爲解決這些問題,需要探索公司是如何運作的。在開始重構之前,回答以下幾個問題:

  • 什麼任務優先級最高?

  • 開發的速度是什麼樣的?

  • 開發人員是否感到快速交付代碼很有壓力?

  • 有哪些處理技術債務的流程?

  • 進行了哪些類型的代碼評審?

  • 你的團隊是否具備相應的重構技能?

  • 公司針對文檔的標準是什麼?

如果不解決導致需要重構的根本問題,問題只會擴散。

 

08

高級管理層對重構的支持

在你的公司,基礎設施和維護方面的投資可能不受待見。有些人會想當然地認爲,花費在重構上的時間就是佔用了做新工作的時間。但我們有必要着眼於重構所帶來的更大好處,以及它們與工作流、客戶、收入和業務增長之間的關係。重構如果做得好,可以改進代碼,使其能夠很好地運行,從而交付有效的更新和趨勢特性,從而吸引新客戶和回訪客戶。這就是軟件公司如何在成功發佈產品後保持競爭力的方式。

更好的做法是,量化團隊當前花費了多少時間修復原始代碼中的錯誤或 bug,從而從高級管理人員那裏獲得對重構的支持。具體一點,是每天一個小時嗎?還是一天兩個小時?堅持記錄至少一週,你可能會驚訝地發現你的團隊每年花費了好幾周甚至好幾個月的時間來修復遺留代碼。

 

09

團隊支持和重構:衝刺還是馬拉松?

 

 

圖片

 

你的團隊很難接受重構嗎?一提到它,大家就會抱怨嗎?成功重構的最顯著標志是有計劃的、有目的的和文檔化的措施。Ron Jeffries 是極限編程軟件開發方法論的三位創始人之一,他把重構比作清理一塊地):“我們先犁好土地,清除雜草,然後再去播種,也就是構建下一個功能,而不是繞過所有的雜草和灌木叢。”

https://ronjeffries.com/xprog/articles/refactoring-not-on-the-backlog/

然而,他強調,糟糕的代碼需要很長時間來清理,他建議首先要經過充分地思考,而不是一頭直接扎進去:“我們改進我們當前用得到代碼,忽略那些用不到的代碼。很可能,我們下一次會再回來看這塊代碼。通常在同一個衝刺中,我們會發現後續功能實際上使用了我們之前清理過的區域。我們馬上就從增量重構中獲益了。如果我們等着大規模地實施,就需要投入更多的精力,同時也推遲了產出收益的時間,很可能會把精力浪費在不會帶來收益的地方。”

產品工程師和 CTO Andreas Klinger 是“週五處理”的粉絲。“週五處理的原則很簡單:除非你當前的項目很忙,否則就利用週五做一些小的改進。讓工程師選擇他們要做的工作。不要因爲太過細緻的管理導致大家失去工作的樂趣。一些人會嘗試新的類庫。有些人會消除待辦事務中的缺陷。這兩個都很好。試着促使任務平衡。”

無論你的方法是什麼,都需要用心思考。問問你的團隊什麼代碼最妨礙他們的效率。

  • 修改什麼代碼對其他代碼的影響最大?

  • 修改什麼將帶來最大的回報?

誰都不可能在重構上花費大量的時間而犧牲其他項目,但是不要低估常規的、一貫的、專門的小型重構的影響。積沙成塔,一點一滴堆積起來就會帶來巨大的好處。

 

10

文檔和重構

標準化命名約定之類的文檔可以確保每個人形成共同的認知。施樂高級開發人員在研究重構時發現,缺乏文檔是最大的挑戰之一。

將你重構所做的工作記錄下來,可以跟蹤所花費的時間,併爲未來的團隊成員提供上下文。同時,把你取得的成功記錄下來——重構中取得的最大的勝利是什麼?這些可以進行同行評審嗎?

原文鏈接:

https://www.stepsize.com/blog/the-ultimate-engineers-guide-to-refactoring

本文轉載自微信公衆號:架構頭條。

 

文章看完,還不過癮?

更多精彩內容歡迎關注百度開發者中心公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章