什么是重構(gòu)
重構(gòu)(名詞):對軟件內(nèi)部結(jié)構(gòu)的一種調(diào)整,目的是在不改變軟件可觀察行為的前提下,提高其可理解性,降低其修改成本。
重構(gòu)(動詞):使用一系列重構(gòu)手法,在不改變軟件可觀察行為的前提下,調(diào)整其結(jié)構(gòu)。
重構(gòu)的關(guān)鍵在于運(yùn)用大量微小且保持軟件行為的步驟,一步步達(dá)成大規(guī)模的修改。每個單獨(dú)的重構(gòu)要么很小,要么由若干小步驟組合而成。
可觀察行為:整體而言,經(jīng)過重構(gòu)之后的代碼所做的事應(yīng)該與重構(gòu)之前大致一樣。
重構(gòu)與性能優(yōu)化有很多相似之處:兩者都需要修改代碼,并且兩者都不會改變程序的整體功能。兩者的差別在于其目的:重構(gòu)是為了讓代碼“更容易理解,更易于修改”。這可能使程序運(yùn)行得更快,也可能使程序運(yùn)行得更慢。在性能優(yōu)化時,只關(guān)心讓程序運(yùn)行得更快,最終得到的代碼有可能更難理解和維護(hù)。
兩頂帽子
這是一個比喻,使用重構(gòu)技術(shù)開發(fā)軟件時,我把自己的時間分配給兩種截然不同的行為:添加新功能和重構(gòu)。添加新功能時,我們不應(yīng)該修改既有代碼,只管添加新功能。重構(gòu)時我們就不餓能添加功能,只管調(diào)整代碼的結(jié)構(gòu)。
實際開發(fā)過程中,我們可能需要經(jīng)常變換帽子。如果把程序結(jié)構(gòu)改一下,功能的添加會容易得多;新功能添加好了以后發(fā)現(xiàn)代碼難以理解,則繼續(xù)重構(gòu)。
為何重構(gòu)
我們之所以重構(gòu),因為它能讓我們更快——添加功能更快,修復(fù)bug更快。
重構(gòu)改進(jìn)軟件的設(shè)計
沒有重構(gòu),程序的內(nèi)部設(shè)計(架構(gòu))會逐漸腐敗變質(zhì)。當(dāng)人們只為短期目的而修改代碼時,他們經(jīng)常沒有完全理解架構(gòu)的整體設(shè)計,于是代碼逐漸失去了自己的結(jié)構(gòu)。程序員越來越難通過閱讀源碼來理解原來的設(shè)計。
經(jīng)常性的重構(gòu)有助于代碼維持自己該有的形態(tài)。
重構(gòu)使軟件更容易理解
寫讓計算機(jī)理解的代碼很容易,只要能編譯通過并運(yùn)行;但寫出讓別人能理解的代碼則需要下點(diǎn)功夫了。所以我們寫代碼要考慮以后那個修改的人,而且那個人很可能是哦我們自己。
開始進(jìn)行重構(gòu)前,代碼可以正常運(yùn)行,但結(jié)構(gòu)不夠理想。在重構(gòu)上花一點(diǎn)點(diǎn)時間,就可以讓代碼更好地表達(dá)自己的意圖。
重構(gòu)幫助找到Bug
對代碼進(jìn)行重構(gòu),就可以深入理解代碼的所作所為,并立即把新的理解反映在代碼當(dāng)中。搞清楚程序結(jié)構(gòu)的同時,也驗證了所做的一些假設(shè), 更容易將Bug找出來。重構(gòu)能夠幫助我們更有效地寫出健壯的代碼。
重構(gòu)提高編程速度
設(shè)計耐久性假說:通過投入精力改善內(nèi)部設(shè)計,我們增加了軟件的耐久性,從而可以更長時間地保持開發(fā)的快速。
行業(yè)的陳規(guī)認(rèn)為:良好的設(shè)計必須在開始編程之前完成,因為一旦開始編寫代碼,設(shè)計就只會逐漸腐敗。重構(gòu)改變了這個圖景。現(xiàn)在我們可以改善已有代碼的設(shè)計,因此我們可以先做一個設(shè)計,然后不斷改善它,哪怕程序本身的功能也在不斷發(fā)生著變化。由于預(yù)先做出良好的設(shè)計非常困難,想要既體面又快速地開發(fā)功能,重構(gòu)必不可少。
何時重構(gòu)
三次法則
- 第一次做某件事時只管去做
- 第二次做類似的事會產(chǎn)生反感,但無論如何還是可以去做
- 第三次再做類似的事,你就應(yīng)該重構(gòu)。
預(yù)備性重構(gòu):讓添加新功能更容易
重構(gòu)的最佳時機(jī)就在添加新功能之前。例如有個函數(shù)提供了我們需要的大部分功能,只是有幾個變量跟我們需要的沖突,通常我們的做法使把這個函數(shù)復(fù)制過來,修改幾個值。這樣做會導(dǎo)致重復(fù)代碼(將來有可能需要修改兩處)。使用函數(shù)參數(shù)化(310)進(jìn)行重構(gòu)后,只需要調(diào)用這個函數(shù),傳入需要的參數(shù)。
修復(fù)bug時的情況也是一樣。在尋找問題根因時,可能會發(fā)現(xiàn):如果把3段一模一樣且都會導(dǎo)致錯誤的代碼合并到一處,問題修復(fù)起來會容易得多。
幫助理解的重構(gòu):使代碼更易懂
重構(gòu)帶來的幫助不僅發(fā)生在將來——常常是立竿見影。先在一些小細(xì)節(jié)上使用重構(gòu)來幫助理解,給一兩個變量改名,讓它們更清楚地表達(dá)意圖,以方便理解,或是將一個長函數(shù)拆成幾個小函數(shù)。當(dāng)代碼變得更清晰一些時就會看見之前看不見的設(shè)計問題。
撿垃圾式重構(gòu)
幫助理解的重構(gòu)還有一個變體:已經(jīng)理解代碼在做什么,但發(fā)現(xiàn)它做得不好,例如邏輯不必要地迂回復(fù)雜,或者兩個函數(shù)幾乎完全相同,可以用一個參數(shù)化的函數(shù)取而代之。有兩種處理方式:如果垃圾很容易重構(gòu),馬上重構(gòu)它;如果重構(gòu)需要花一些精力,記錄下來,完成當(dāng)下的任務(wù)再回來重構(gòu)它。
有計劃的重構(gòu)
一般項目計劃上沒有專門留給重構(gòu)的時間,絕大多數(shù)重構(gòu)都在做其他事的過程中自然發(fā)生。如果團(tuán)隊過去忽視了重構(gòu),那么常常會需要專門花一些時間來優(yōu)化代碼庫,以便更容易添加新功能。
長久以來,人們認(rèn)為編寫軟件是一個累加的過程:要添加新功能,我們就應(yīng)該增加新代碼。但優(yōu)秀的程序員知道,添加新功能最快的方法往往是先修改現(xiàn)有的代碼,使新功能容易被加入。所以,軟件永遠(yuǎn)不應(yīng)該被視為“完成”。每當(dāng)需要新能力時,軟件就應(yīng)該做出相應(yīng)的改變。越是在已有代碼中,這樣的改變就越顯重要。
何時不應(yīng)該重構(gòu)
如果有一塊凌亂的代碼,但并不需要修改它,那么就不需要重構(gòu)它。如果丑陋的代碼能被隱藏在一個API之下,暫時容忍它繼續(xù)保持丑陋。只有當(dāng)需要理解其工作原理時,對其進(jìn)行重構(gòu)才有價值。
另一種情況是,如果重寫比重構(gòu)還容易,就別重構(gòu)了。
重構(gòu)的挑戰(zhàn)
延緩新功能開發(fā)
很多人認(rèn)為,花在重構(gòu)的時間是在拖慢新功能的開發(fā)進(jìn)度?!爸貥?gòu)會拖慢進(jìn)度”這種看法仍然很普遍,這可能是導(dǎo)致人們沒有充分重構(gòu)的最大阻力所在。
重構(gòu)的唯一目的就是讓我們開發(fā)更快,用更少的工作量創(chuàng)造更大的價值。
有一種情況確實需要權(quán)衡取舍:有時會看到一個(大規(guī)模的)重構(gòu)很有必要進(jìn)行,而馬上要添加的功能非常小,這時可以先把新功能加上,然后再做這次大規(guī)模重構(gòu)。
測試
如果開發(fā)環(huán)境(開發(fā)工具)能很好的支持自動化重構(gòu),則可以信任這些重構(gòu);如果不能最好有完備的測試套件(測試環(huán)境、測試代碼、單元測試等)。
遺留代碼
遺留代碼往往很復(fù)雜,可能也沒有充足的測試,關(guān)鍵還是別人寫的。如果不幸遇到,沒有什么好辦法:沒測試就加測試、隨時重構(gòu)相關(guān)的代碼(不建議嘗試一鼓作氣把復(fù)雜而混亂的遺留代碼重構(gòu)成漂亮的代碼)。
重構(gòu)、架構(gòu)和YAGNI
YAGNI:“你不需要它(you are`t going to need it)”。YAGNI并不是“不做架構(gòu)性思考”的意思,不過確實有人以這種欠考慮的方式做事。
重構(gòu)對架構(gòu)最大的影響在于,通過重構(gòu),我們能得到一個設(shè)計良好的代碼庫,使其能夠優(yōu)雅地應(yīng)對不斷變化的需求?!霸诰幋a之前先完成架構(gòu)”這種做法最大的問題在于,它假設(shè)了軟件的需求可以預(yù)先充分理解。但經(jīng)驗顯示,這個假設(shè)很多時候甚至可以說大多數(shù)時候是不切實際的。只有真正使用了軟件、看到了軟件對工作的影響,人們才會想明白自己到底需要什么。
重構(gòu)與軟件開發(fā)過程
重構(gòu)是否有效,與團(tuán)隊采用的其他軟件開發(fā)實踐緊密相關(guān)。
重構(gòu)的第一塊基石是自測試代碼。
如果一支團(tuán)隊想要重構(gòu),那么每個團(tuán)隊成員都需要掌握重構(gòu)技能,能在需要時開展重構(gòu),而不會干擾其他人的工作。
自測試代碼、持續(xù)集成、重構(gòu)三者之間有著很強(qiáng)的協(xié)同效應(yīng)。
重構(gòu)與性能
重構(gòu)可能使軟件運(yùn)行更慢,但它也使軟件的性能優(yōu)化更容易。先寫出可調(diào)優(yōu)的軟件,然后調(diào)優(yōu)它以求獲得足夠的速度。
編寫構(gòu)造良好的程序,不對性能投以特別的關(guān)注,直至進(jìn)入性能優(yōu)化階段——那通常是在開發(fā)后期。一旦進(jìn)入該階段,再遵循特定的流程來調(diào)優(yōu)程序性能。文章來源:http://www.zghlxwxcb.cn/news/detail-673869.html
在性能優(yōu)化階段,首先應(yīng)該用一個度量工具來監(jiān)控程序的運(yùn)行,讓它告訴我程序中哪些地方大量消耗時間和空間。這樣就可以找出性能熱點(diǎn)所在的一小段代碼。然后集中關(guān)注這些性能熱點(diǎn),并使用持續(xù)關(guān)注法中的優(yōu)化手段來優(yōu)化它們。文章來源地址http://www.zghlxwxcb.cn/news/detail-673869.html
到了這里,關(guān)于CH02_重構(gòu)的原則(什么是重構(gòu)、為什么重構(gòu)、何時重構(gòu))的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!