轉:https://www.cnblogs.com/ludashi/p/5223241.html
重構是項目做到一定程度后必然要做的事情。代碼重構,可以改善既有的代碼設計,增強既有工程的可擴充、可維護性。隨着項目需求的不斷迭代,需求的不斷更新,我們在項目中所寫的代碼也在時時刻刻的在變化之中。在一次新的需求中,你添加了某些功能模塊,但這些功能模塊有可能在下一次需求中不在適用。或者你因為需求迭代與變更,使你原有的方法或者類變得臃腫,以及各個模塊或者層次之間耦合度增加。此時,你要考慮重構了。
重構,在《重構,改善既有代碼的設計》這本經典的書中給出了定義,大概就是:在不改變代碼對外的表現的情況下,修改代碼的內部特征。說白了,就是我們的測試用例不變,然后我們對既有的代碼的結構進行修改。重構在軟件開發中是經常遇到的,也是非常重要的。在需求迭代,Debug,Code Review時,你都可以對你既有的代碼進行重構。
在接下來的幾篇博文中,我想與大家一塊去窺探一下代碼重構的美麗,學習一下代碼重構的一些規則。當然在每個規則中都有小的Demo, 在本篇博客以及相關內容的博客是使用Swift語言實現的。當然,和設計模式相同,重構重要的是手法和思想,和使用什么樣的語言關系不大。經典的重構書籍中是使用Java語言來實現的,如果你對PHP, Python等其他語言比較熟悉,完全可以使用這些語言來測試一些重構手法。
本篇博客的主題就是通過一些列的重構手法,對既有的需要重構的函數或者方法進行重構。並且會將每個示例在GitHub上進行分享,感興趣的小伙伴可以對其進行下載。有的小伙伴說了,我沒有Mac,怎么對你寫的Swift代碼進行編譯呢?這個問題好解決,你可以看我之前發表的這篇博客《窺探Swift之使用Web瀏覽器編譯Swift代碼以及Swift中的泛型》。你可以將相關代碼進行拷貝,在瀏覽器中觀察結果。因為在線編譯的網站是國外的,訪問起來也許會有一些卡頓,不過是可以用的。好前面扯了這么多了,進入今天的主題。
一、Extract Method(提取函數)-------將大函數按模塊拆分成幾個小的函數
Extract Method被翻譯成中文就是提取函數的意思,這一點在代碼重構中用的非常非常的多。在重構時提倡將代碼模塊進行細分,因為模塊越小,可重用度就越大。不要寫大函數,如果你的函數過大,那么這意味着你的函數需要重構了。因為函數過大,可維護性,可理解性就會變差。並且當你實現類似功能的時候就容易產生重復代碼。寫代碼時,最忌諱的就是代碼重復。這也就是經常所說的DRY(Don`t Repeat Yourself)原則。所以當函數過長時,你需要將其細分,將原函數拆分成幾個函數。
下方將會通過一個示例來直觀的感受一下Extract Method,當然這些示例不是我原創的,是《重構:改善既有代碼的設計》中Java示例演變的Swift版,在寫Swift代碼時,對原有的示例進行了一些修改,算是偽原創吧。不過目的只有一個:希望與大家交流分享。實在是沒有必要再找其他的例子說明這些重構規則,因為《重構:改善既有的代碼的設計》這本書真的是太經典了。
1.需要重構的代碼如下所示。下方代碼中的MyCustomer類中有兩個常量屬性,並且該類提供了一個構造器。該類還提供了一個輸出方法,就是第一該類中的屬性進行打印說明,其實該類中沒有什么功能
在寫好需要重構的類后,我們要為該類寫一個測試用例。這便於在我們重構時對重構的正確性進行驗證,因為每次重構后都要去執行該測試用例,以保證我們重構是正確的。下方截圖就是為上方示例寫的測試用例以及該測試用例的打印結果。當然重構后我們也需要調用該測試用例,並觀察打印結果是否與之前的一致。當然如果你不想自己觀察,你可以為上面的類添加相應的單元測試,這也是在常規項目中經常使用的。至於如果添加測試用例,我們會在后面的博客中進行詳細介紹。下方就是上述類的測試用例和輸出結果:
2.接下來我們對上面類中的printOwning函數進行分析。上述類可以正常工作,這是肯定的。但是printOwning()函數寫的不夠好。因為它干了太多的事情,也就是說該函數包括了其他子模塊,需要對其進行拆分。由上面截圖中的紅框可以看出,每個紅框就代表着一個獨立的功能模塊,就說明這一塊代碼可以被拆分成獨立的函數。在拆分子函數時,我們要為該函數起一個與改代碼塊功能相符合的名字。也就是說當你看到該函數名字時,你就應該知道該函數是干嘛的。
下方代碼段就是我們重構后的類。說白的,就是對函數中可以進行獨立的模塊進行提取,並為提取的新的函數命一個合適的名稱。經過重構后printOwing()函數就只有兩行代碼,這樣看其中調用的函數名也是很容易理解其作用的。下方拆分出來的三個函數也是一個獨立的模塊,因為函數短小,所以易於理解,同時也易於重用。經過Extract Method,當然好處是多多的。經過重構后的代碼,我在調用上述的測試用例,輸出結果和原代碼是一直的,如果不一致的話,那么說明你的重構有問題呢,需要你進行Debug。