




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、一重構原那么1、何謂重構對軟件內部結構的一種調整,目的是在不改變軟件可觀察行為的前提下,提升其可理解性,降低其修改本錢.另一種解釋是:使用一系列重構手法,在不改變軟件可觀察行為的前提下,調整其結構.重構不止是代碼整理,它提供了一種高效且受控的代碼整理技術2、為何重構?改良軟件設計: 如果沒有重構,程序的設計會逐漸變質,重構很像是在整理代碼,你所做的就是讓所有的東西回到應處的位置上.?幫助找到bug:對代碼進行重構,可以深入理解代碼的作為,在搞清楚程序結構的同時,想不把bug揪出來都難.?提升編程速度:良好的設計是快速開發(fā)的根本,改善設計、提升可讀性,減少錯誤,這些都是提升質量.3、何時重構任何
2、情況下我都反對專門撥出時間進行重構.重構本來就不是一件應該特別撥出時間做的事情,重構應該隨時隨地的進行.三次法那么第一次做某件事情是只管去做; 第二次做類似的事情會產(chǎn)生反感;第三次再做類似的事,你就應該重構?最常見的重構時機是想給軟件添加新特性的時候;重構的另個一原動力是:代碼的設計無法幫助我輕松的添加所需要的特性?修改錯誤的時候?review代碼的時重構I可接層和重構計算機科學是這樣一門科學:它相信所有的問題都可以通過增加一個間接層來解決.大多數(shù)重構都為程序引入了更多的間接層,重構往往把大型的對象拆成多個小型的對象,把大型的函數(shù)拆成多個小型的函數(shù).但是,間接層是一把雙刃僉I.每次把一個東西分
3、成兩份,你就需要多治理一個東西.如果某個對象委托另一個對象,后者又委托另一個對象,程序會愈加難以閱讀.何時不該重構:有時候既有代碼實在太混亂,重構它還不如重新寫一個來得簡單.重寫而非重構的一個清楚訊號是:現(xiàn)有代碼根本不能正常運作.二代碼的壞味道1、重復代碼如果你在一個以上的地點看到相同的程序結構,那么可以肯定: 設法將它們合二為一,程序會變得更好.1 .同一個類中有相同的表達式:提煉出重復的代碼,然后讓兩個地方都調用被提煉出來的那一段代碼;2.兩個互為兄弟的子類內含有相同的表達式:提煉出相同代碼,將它推入超類內;3.兩個毫不相干的類中出現(xiàn):將重復的代碼提煉到一個獨立的類中.2、過長的類擁有短函
4、數(shù)的對象活得比擬好、比擬長.間接層所能帶來的全部利益解釋水平、共享水平、選擇水平都是由小型函數(shù)支持的.每當感覺需要以注釋來說明點什么的時候,我們就把需要說明的東西寫進一個獨立的函數(shù)中.如何確定提煉哪一段代碼?尋找注釋是一個很好的技巧.它們通常能指出代碼用途和實現(xiàn)手法之間的語義距離.如果代碼前方有一行注釋,就是提醒你: 可以將這段代碼替換成一個函數(shù).條件表達式和循環(huán)常常也是提煉的信號.3、過大的類如果想利用單個類做太多的事情,其內往往就會出現(xiàn)太多實力變量.類內如果有太多代碼,也是代碼重復、混亂病最終走向死亡的源頭.4、過長參數(shù)列太長的參數(shù)列難以理解,太多的參數(shù)會造成前后不一致、 不容易使用,而且
5、一旦你需要更多數(shù)據(jù),就不得不修改它.如果將對象傳遞給函數(shù),大多數(shù)修改都將沒有必要.5、發(fā)散式變化如果某個類經(jīng)常由于不同的原因在不同的方向上發(fā)生變化,那么此時也許將這個對象分成兩個會更好,這么一來每個對象就可以只由于一種變化而需要修改.6、散彈式修改如果沒遇到某種變化,你都必須在許多不同的類內做出許多小修改,你所面臨的壞味道就是散彈式修改.如果需要修改的代碼散布四處,你不但很難找到它們,也很容易忘記某個重要的修改.把所有需要修改的代碼放進同一個類中,如果眼下沒有適宜的類可以安置這些代碼就創(chuàng)造一個.7、依戀情結對象技術的要點在于:將數(shù)據(jù)和對數(shù)據(jù)的操作行為包裝在一起有一種經(jīng)典的氣味是:函數(shù)對某個類的
6、興趣高過對自己所處類的興趣.某個函數(shù)為了計算某個值,從另一個對象那調用幾乎半打的取信函數(shù).一個函數(shù)往往會用到幾個類的功能,那么它該置于何處?我們的原那么是:判斷哪個類擁有最大被此函數(shù)使用的數(shù)據(jù),然后就把這個函數(shù)和那些數(shù)據(jù)放在一起.8、數(shù)據(jù)泥團很多地方看到相同的三四項數(shù)據(jù)一起出現(xiàn).這些總是綁在一起出現(xiàn)的數(shù)據(jù)應該擁有屬于他們自己的對象.首先找到這些數(shù)據(jù)以字段形式出現(xiàn)的地方,將它們提煉到一個獨立的對象中.這么做的直接好處是可以將很多參數(shù)列縮短簡化函數(shù)調用.9、根本類型偏執(zhí)對象的一個極大價值在于: 它們模糊了橫且與根本數(shù)據(jù)和體積較大的類之間的界限對象技術的新手通常不愿意在小任務上運用小對象一一結合數(shù)值
7、和比重的money類、有一個起始值和一個結束值組成的range類.將原本單獨存在的數(shù)值替換成對象,從而走出傳統(tǒng)的洞窟,進入炙手可熱的對象世界.10、switch驚悚現(xiàn)身面向對象的一個最明顯的特征是: 少用switch語句一看到switch語句,就應該考慮以多態(tài)來替換它.如果只是在單一函數(shù)中有些選擇實例,且并不想改動它們,那么多態(tài)就有點殺雞用牛刀了.11、平行集成體系每當你為某個類增加一個子類,必須也為另一個類相應增加一個子類.消除這種重復性的一般策略是:讓一個繼承體系的實例引用另一個繼承體系的實例.12、冗余類某個類原本對得起自己的身價,但重構使它身形縮水,不再做那么多工作,這個時候請讓這個類
8、莊嚴赴義吧.13、夸夸其談未來性企圖以各種各樣的鉤子和特殊情況來處理一些非必要的事情,這種懷味道就出現(xiàn)了.如果用到了那就值得去做,如果用不到那就不值得,只會擋你的路,所以把它挪開吧.如果你的某個抽象類其實沒有起到太大的作用,函數(shù)上的某些參數(shù)未被使用.可以移除它們了.14、令人迷惑的暫時字段某個實例變量僅為某種特定的情況而設.這樣的代碼讓人不易理解.在變量未被使用的情況下猜想當初其設置目的,會讓你發(fā)瘋的.15、過度耦合消息鏈如果你看到用戶向一個對象請求另一個對象,然后再向后者請求另一個對象,然后再請求另個一對象這就是消息鏈.采用這種方式,意味著客戶代碼將與查找過程中的導航結構緊密耦合.一旦對象間
9、的關系發(fā)生任何變化,客戶端就不得不做出相應的修改.16、中間人封裝往往伴隨著委托.你也許會看到某個類接口有一半的函數(shù)都委托給其他類,這樣就是過度運用.17、狎昵關系有時會看到兩個類過于親密,話費太多的時間去探究彼此的private成分.過分狎昵的類必須拆散,幫它們劃清界線,從而減少狎昵行徑.繼承往往造成過度親密,由于子類對超類的了解總是超過后者的主觀愿望.如果你覺得該讓孩子獨立生活了,讓他離開繼承.18、異曲同工的類兩個函數(shù)做同一件事,卻有著不同的簽名.19、不完美的類庫類庫函數(shù)構造的不夠好,又不能修改它們:1 .如果只想修改類的一兩個函數(shù),可以引入外加函數(shù).2.如果想要添加一大堆額外行為,建
10、立一個新類包含這些額外行為,讓其成為子類.20、純稚的數(shù)據(jù)類純稚的數(shù)據(jù)類是指:它們擁有一些字段,以及用于訪問讀寫這些字段的函數(shù),除此之外一無長物.封裝public字段;恰當封裝容器類字段;移除不應修改的字段的設置函數(shù);提煉調用函數(shù)以隱藏取值/設值函數(shù);21、被拒絕的遺贈子類只運用了父類的一局部函數(shù)和數(shù)據(jù).為子類建立一個兄弟類,將所有用不到的字段/函數(shù)下移至兄弟類,保證超類的純粹;22、過多的注釋注釋之所以存在是由于代碼很糟糕.注釋的最高境界一一代碼即注釋.當你感覺需要撰寫注釋時,請先嘗試重構,試著讓所有的注釋都變得多余.三重新組織函數(shù)1、提煉函數(shù)動機:看到一個過長的函數(shù)或者一段需要注釋才能讓人
11、理解用途的代碼,將這段代碼放一個獨立的函數(shù)中;做法:?創(chuàng)造一個新函數(shù),根據(jù)這個函數(shù)的意圖來命名它;只要新函數(shù)的名稱能夠以更好的方式昭示代碼意圖,你也應該提煉它.但如果想不到一個更有意義的名稱就別動?將提煉的代碼從原函數(shù)復制到新建的目標函數(shù)中;?將被提煉代碼段中需要讀取的局部變量,當作參數(shù)傳遞給目標函數(shù);?在源函數(shù)中,將被提煉代碼段替換為目標函數(shù)調用.2、內聯(lián)函數(shù)一個函數(shù)的本體與名稱同樣清楚易懂.在函數(shù)調用點插入函數(shù)本體,然后移除該函數(shù).動機:?一群組織不甚合理的函數(shù).你可以將它們都內聯(lián)到一個大函數(shù)中,再從中提煉出組織合理的小型函數(shù).?使用的太多的間接層,使得系統(tǒng)中的所有函數(shù)都似乎只是對另一個函
12、數(shù)的簡單委托,造成在委托動作之間暈頭轉向.做法:?檢查函數(shù),確定不具備多態(tài);如果子類繼承了這個函數(shù),就不要將此函數(shù)內聯(lián),由于子類無法復寫一個根本不存在的函數(shù).?找出這個函數(shù)的所有調用點;?將這個函數(shù)的所有調用點都替換成函數(shù)本體.3、內聯(lián)臨時變量有一個臨時變量,只被一個簡單的表達是賦值一次,而它阻礙了其他重構手法.將所有對該變量的引用動作,替換為對它賦值的那個表達式自身doublebasePrice=anOrder.basePrice();return(base10000);替換為:return(anOrder.basePrice1000);4、以查詢取代臨時變量你的程序以一個臨時變量保存某一表
13、達式的運算結果.將這個表達式提煉到一個獨立的函數(shù)中.將這個臨時變量的所有引用點替換為對新函數(shù)的調用.此后,新函數(shù)就可被其他函數(shù)使用.doublebasePrice=quantity*timePrice;if(basePrice1000)returnbasePrice*09.5;elsereturnbasePrice*0.98;替換為:if(basePrice()1000)returnbasePrice*09.5;elsereturnbasePrice*0.98;doublebasePrice()returnquantity*timePrice;臨時變量只在所屬的函數(shù)中可見,如果把臨時變量替換為
14、一個查詢,那么同一個類中的所有函數(shù)都將可以獲得這個份信息,這將帶給你極大的幫助,使你能夠為這個類編寫更清楚的代碼.5、引入注釋性變量你有一個復雜的表達式.將該復雜表達式(或其中一局部)的結果放進一個臨時變量,以此變量名稱來解釋表達式用途.if(platform.toUpperCase().indexOf(MAC)-1)&(browser.toUpperCase().indexOf(IE)-1)&wasInitialized()&resize0)/dosmothing替換為:finalbooleanisMacOs=platform.toUpperCase().indexO
15、f(MAC)-1;finalbooleanisIEBrowser=browser.toUpperCase().indexOf(IE)-1;finalbooleanwasResized=resize0;if(isMacOs&isIEBrowser&wasInitialized()&wasResized)/dosmothing表達式有可能非常復雜難以理解.這種情況下,臨時變量可以幫助你將表達式分解為比擬容易治理的形式.在條件邏輯中,你可以用這項重構將每個條件子句提煉出來,以一個良好命名的臨時變量來解釋對應條件子句的意義.另一種情況是: 在較長的算法中,可以運用臨時變量來解釋
16、每一步運算的意義.6、分解臨時變量你的程序有某個臨時變量被賦值超過一次,它既不是循環(huán)變量,也不被用于收集計算結果.針對每次賦值,創(chuàng)造一個獨立、對應的臨時變量.doubletemp=2*(height+width);Systemout.println(temp);temp=height*width;Systemout.println(temp);替換為:doubleperimeter=2*(height+width);Systemout.println(perimeter);doublearea=height*width;Systemout.println(area);如果臨時變量被賦值超過一次
17、,就意味著它們在函數(shù)中承當了一個以上的責任.如果臨時變量承當多個責任,它就應該被替換為多個臨時變量.每個變量只承當一個責任,同一個臨時變量承當兩件不同的事情會令代碼閱讀者糊涂7、移除對參數(shù)的賦值代碼對一個參數(shù)進行復制.以一個臨時變量取代該參數(shù)的位置.intdiscount(intinputVal,intquantity,intyearToData)if(inputVal50)inputVal-=2;替換為:intdiscount(intinputVal,intquantity,intyearToData)intresult=inputVal;if(inputVal50)result-=2;如果
18、代碼的語義是按引用傳遞的,請在調用段檢查調用后是否還使用了這個參數(shù).8、替換算法想要把某個算法替換為另一個更清楚的算法.將函數(shù)本體替換成為另一個算法.StringfoundPerson(Stringpeople)for(inti=0;ipeople.length;i+)if(peoplei.equals(Don)returnDon;if(peoplei.equals(John)returnJohn;if(peoplei.equals(Kent)returnKent;return;替換為:StringfoundPerson(Stringpeople)Listcandidates=Arrays.a
19、sListnewStringDon,John,Kent);for(inti=0;i=low&arg=getLow()&arg=getHigh();intgetLow()retrunlow;intgetHigh()returnhigh;在“字段訪問方式這個問題上,存在兩種截然不同的觀點:1 .在該變量定義所在的類中,你可以自由的訪問.2.即使在這個類中你也應該只使用訪問函數(shù)間接訪問.間接訪問的好處是:子類可以通過復寫一個函數(shù)而改變獲取數(shù)據(jù)的途徑;它支持更靈活的數(shù)據(jù)治理方式,例如延遲初始化.2、以對象取代數(shù)據(jù)值你有一個數(shù)據(jù)項,需要與其他數(shù)據(jù)和行為一起使用才有意義.將數(shù)據(jù)項變?yōu)閷ο?
20、一開始你肯能會用一個字符串來表示“號概念,但是隨后你會發(fā)現(xiàn),號需要“格式化、“區(qū)號之類的行為.這時候就需要為帶替換的數(shù)值新建一個類.3、將值對象改為引用對象你從一個類衍生出許多彼此相等的實例,希望將它們替換為同一個對象.將這個值對象變成引用對象.4、將引用對象改為值對象你有一個引用對象,很小且不可改變,而且不易治理.將它變成一個值對象.5、以對象取代數(shù)組你有一個數(shù)組,其中的元素各自代表不同的東西.以對象替換數(shù)組.對于數(shù)組中的每個元素,以一個字段來表示6、 復制被監(jiān)視數(shù)據(jù)你有一些領域數(shù)據(jù)置身GUI控件中,而領域函數(shù)需要訪問這些數(shù)據(jù).將該數(shù)據(jù)復制到一個領域對象中.建立一個Observer模式,用以
21、同步領域對象和GUI對象內的重復數(shù)據(jù).7、將單向關聯(lián)改為雙向關聯(lián)兩個類都需要使用對方特性,但其間只有一條單向連接.添加一個反向指針,并使修改函數(shù)能夠同時更新兩條連接.8、將雙向關聯(lián)改為單向關聯(lián)兩個類之間有雙向關聯(lián),但其中一個類如今不再需要另一個類的特性.去除不必要的關聯(lián).9、以字面常量取代魔數(shù)你有一個字面數(shù)值,帶有特別含義.創(chuàng)造一個常量,根據(jù)其意義為它命名,并將上述的字面數(shù)值替換為常量.10、封裝字段你的類中存在一個public字段.將它聲明為private,并提供相應的訪問函數(shù).11、封裝集合有個函數(shù)返回一個集合.讓這個函數(shù)返回該集合的一個只讀副本,并在這個類中提供添力口/移除集合元素的函數(shù)
22、.六簡化條件表達式1、分解條件表達式有一復雜的條件語句.從if、then、else三個段落中分別提煉出獨立函數(shù).2、合并表達式你有一系列條件測試,都得到相同結果.將這些測試合并為一個條件表達式,并將這個條件表達式提煉成一個獨立函數(shù).3、合并重復的條件代碼在表達式的每個分支上都執(zhí)行了相同的一段代碼.將這段重復代碼搬移到條件表達式之外.4、移除限制標記在一系列布爾表達式中,某個變量帶有“限制標記的作用.以break/return語句取代限制標記.5、以多態(tài)取代條件表達式有個條件表達式根據(jù)對象類型的不同而選擇不同的行為.將這個條件表達式的每個分支放進一個子類內的覆寫函數(shù)中,然后將原始函數(shù)聲明為抽象函
23、數(shù)七簡化函數(shù)調用1、函數(shù)改名函數(shù)的名稱未能揭示其用途.修改函數(shù)名稱.2、添加參數(shù)某個函數(shù)需要從調用端得到更多信息.為此函數(shù)添加一個對象參數(shù),讓該對象帶僅函數(shù)所需信息.3、移除參數(shù)函數(shù)本體不再需要某個參數(shù).去除參數(shù).4、別離查詢函數(shù)和修改函數(shù)某個函數(shù)既返回對象狀態(tài)值,又修改對象值.建立兩個不同函數(shù),其中一個負責查詢,另一個負責修改.5、令函數(shù)攜帶參數(shù)假設干函數(shù)做了類似的工作,但在函數(shù)本體中包含了不同的值.建立單一函數(shù),以參數(shù)表達那些不同的值.有這樣兩個函數(shù): 它們做著類似的工作,但因少數(shù)幾個值致使行為略有不同.在這種情況下,你可以將這些各自別離的函數(shù)同一起來,并通過參數(shù)來處理那些變化情況,用以簡化問題.6、以明確函數(shù)取代參數(shù)你有一個函數(shù),其中完全取決于參數(shù)值而采用不同行為.針對該參數(shù)的每一個可能值,建立一個獨立函數(shù).如果某個參數(shù)有多種可能的值,而函數(shù)內又以條件表達式檢查這些參數(shù)值,并根據(jù)不同參數(shù)值做出不同的行為,那么就應該使用本項重構.7、保持對象完整從某個對象中取出假設干值,將它們作為某一次函數(shù)調用時的參數(shù).改為傳遞整個對象.8、以函數(shù)取代參數(shù)對象調用某個函數(shù),并將
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025-2030年中國硬度計市場競爭格局及投資戰(zhàn)略研究報告
- 2025-2030年中國男士護膚品行業(yè)競爭狀況及發(fā)展趨勢分析報告
- 2025-2030年中國電熱線市場運行狀況及前景趨勢分析報告
- 上海工程技術大學《預防口腔醫(yī)學》2023-2024學年第二學期期末試卷
- 沈陽藥科大學《工業(yè)網(wǎng)絡與組態(tài)技術》2023-2024學年第二學期期末試卷
- 中南大學《電動汽車原理與設計》2023-2024學年第二學期期末試卷
- 沈陽航空航天大學北方科技學院《初中道德與法治課程標準與教材》2023-2024學年第二學期期末試卷
- 遼寧中醫(yī)藥大學杏林學院《電工儀表與測量》2023-2024學年第二學期期末試卷
- 廣西金融職業(yè)技術學院《化工熱力學》2023-2024學年第二學期期末試卷
- 2025年安全員《A證》考試題庫
- 四川省瀘州市各縣區(qū)鄉(xiāng)鎮(zhèn)行政村村莊村名居民村民委員會明細
- 《鄒忌諷齊王納諫》課件(共45張)
- 機械制圖教學課件(全套)
- 熱能與動力工程測試技術- 液位測量
- 化學纖維精品課件
- 中式面點師初級(五級)教學計劃、大綱
- QC成果構造柱澆筑新技術的研發(fā)創(chuàng)新(附圖)
- 2020 ACLS-PC-SA課前自我測試試題及答案
- BIM技術應用管理辦法
- 信息論與編碼第4章信息率失真函數(shù)
- 空間幾何向量法之點到平面的距離
評論
0/150
提交評論