好.圈復(fù)雜度概念.重構(gòu)方法及案例.潘洪亮2015-12-03_第1頁
好.圈復(fù)雜度概念.重構(gòu)方法及案例.潘洪亮2015-12-03_第2頁
好.圈復(fù)雜度概念.重構(gòu)方法及案例.潘洪亮2015-12-03_第3頁
好.圈復(fù)雜度概念.重構(gòu)方法及案例.潘洪亮2015-12-03_第4頁
好.圈復(fù)雜度概念.重構(gòu)方法及案例.潘洪亮2015-12-03_第5頁
已閱讀5頁,還剩58頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

揚帆起航圈復(fù)雜度CyclomaticComplexityis17(maxallowedis7).CyclomaticComplexityisX(maxallowedisX)hongliangpan@

我的QQ:28797575知道做什么嗎?文檔示例無目錄有目錄不聚焦不知道目標,不知道總體結(jié)構(gòu)不知道是否合理沒有層次是否有遺漏帶來時間成本質(zhì)量問題4知道做什么嗎?圈復(fù)雜度概念概念計算方法檢查工具二不二重構(gòu)方法案例分析McCabe復(fù)雜度圈復(fù)雜度基本復(fù)雜度模塊設(shè)計復(fù)雜度設(shè)計復(fù)雜度集成復(fù)雜度行數(shù)全局數(shù)據(jù)復(fù)雜度局部數(shù)據(jù)復(fù)雜度病態(tài)數(shù)據(jù)復(fù)雜度規(guī)范化復(fù)雜度框架群:181124238我的QQ:307087558(1)圈復(fù)雜度(CyclomaticComplexity(v(G)))概念圈復(fù)雜度是用來衡量一個模塊判定結(jié)構(gòu)的復(fù)雜程度,數(shù)量上表現(xiàn)為獨立路徑的條數(shù)。計算方法如果一個模塊流程圖有e條邊n個節(jié)點,它的圈復(fù)雜度v(G)=e-n+2。

圈復(fù)雜度(CyclomaticComplexity)是一種代碼復(fù)雜度的衡量標準。它可以用來衡量一個模塊判定結(jié)構(gòu)的復(fù)雜程度,數(shù)量上表現(xiàn)為獨立線性路徑條數(shù),也可理解為覆蓋所有的可能情況最少使用的測試用例數(shù)。圈復(fù)雜度大說明程序代碼的判斷邏輯復(fù)雜,可能質(zhì)量低且難于測試和維護。程序的可能錯誤和高的圈復(fù)雜度有著很大關(guān)系。

圈復(fù)雜度主要與分支語句(if、else、switch、for等)的個數(shù)成正相關(guān)。當一段代碼中含有較多的分支語句,其邏輯復(fù)雜程度就會增加。什么是圈復(fù)雜度示例下面這個實例中,單元測試的覆蓋率可以達到100%,但是很容易發(fā)現(xiàn)這其中已經(jīng)漏掉了一個NPE的測試用例。case1方法的圈復(fù)雜度為2,因此至少需要2個用例才能完全覆蓋到其所有的可能情況。//程序原代碼,圈復(fù)雜度為2

publicStringcase1(intnum){

Stringstring=null;

if(num==1){

string="String";

}

returnstring.substring(0);

}//上面代碼的單元測試代碼

publicvoidtestCase1(){

Stringtest1=case1(1);

}

圈復(fù)雜度主要與分支語句(if、else、,switch等)的個數(shù)成正相關(guān)。當一段代碼中含有較多的分支語句,其邏輯復(fù)雜程度就會增加。圈復(fù)雜度計算概念計算方法檢查工具二不二重構(gòu)方法案例分析示例如果一個模塊流程如下有e條邊n個節(jié)點,它的圈復(fù)雜度v(G)=e-n+2例:

圈復(fù)雜度的計算

圈復(fù)雜度(cyclomaticcomplexity):M=E?N+2P

E:邊的數(shù)量

N:節(jié)點的數(shù)量

P:分離部分的數(shù)量,一般為1,都是聯(lián)通的

圈數(shù)(cyclomaticnumber):M=E?N+P

E,N,P參數(shù)同上

圈復(fù)雜度和圈數(shù)之間的關(guān)系為:

對有向圖A,將A的每個出口(exit)與相應(yīng)的入口(entrance)相連得到有向圖B,則A的圈復(fù)雜度與B的圈數(shù)相等

圈復(fù)雜度又叫做CC復(fù)雜度,也可能被稱為循環(huán)復(fù)雜度,它表達的是if..then..else..,swith..case..,循環(huán)語句等分支語句造成的程序控制流復(fù)雜程度

計算公式補充通常使用的計算公式是V(G)=e–n+2,e

代表在控制流圖中的邊的數(shù)量(對應(yīng)代碼中順序結(jié)構(gòu)的部分),n

代表在控制流圖中的節(jié)點數(shù)量,包括起點和終點(1、所有終點只計算一次,即便有多個return或者throw;2、節(jié)點對應(yīng)代碼中的分支語句)。例如下圖示例一個單入口、單出口的程序圖(不是結(jié)構(gòu)化程序圖),其圈復(fù)雜度為10-7+2=5:從節(jié)點G到A添加一條有向邊,則成為一個強連通有向圖(該方法對其它結(jié)構(gòu)化程序圖同樣適用),其圈數(shù)為11-7+1=5,與上圖的圈復(fù)雜度相同:計算示例

public

Stringcase2(int

index,Stringstring){

StringreturnString=

null;

if

(index<0){

throw

new

IndexOutOfBoundsException("exception<0");

}

if

(index==1){

if

(string.length()<2){

return

string;

}

returnString=

"returnString1";

}

else

if

(index==2){

if

(string.length()<5){

return

string;

}

returnString=

"returnString2";

}

else

{

throw

new

IndexOutOfBoundsException("exception>2");

}

return

returnString;

}根據(jù)公式

V(G)=e–n+2=12–8+2=6

。case2的圈復(fù)雜段為6。說明一下為什么n=8,雖然圖上的真正節(jié)點有12個,但是其中有5個節(jié)點為throw、return,這樣的節(jié)點為end節(jié)點,只能記做一個。計算示例檢查工具概念計算檢查工具二不二重構(gòu)檢查工具開發(fā)中常用的檢測圈復(fù)雜度的工具,PMD,checkstyle都可以檢測到高復(fù)雜度的代碼塊SourceMonitorEclipseMetric插件:有效地查出復(fù)雜度JavaNCSSNCSS表示NonCommentingSourceStatements工具目的Eclipse插件的URLCheckStyle編碼標準分析/update/Coverlipse測試代碼覆蓋率/updateCPD復(fù)制/粘貼檢驗/eclipse/JDepend包依賴項分析http://andrei.gmxhome.de/eclipse/Metrics復(fù)雜度監(jiān)控/update7±2原則概念計算方法檢查工具二不二重構(gòu)方法案例分析直接管好幾百人女:有三室兩廳嗎?男:沒有女:有路虎,奧迪嗎?男:沒有!女:有7位數(shù)存款嗎(?男:沒有+!女:那你有啥?男:我………女轉(zhuǎn)身就走,。突然男的說:我管理幾百人(。。。女立刻回頭抱住男的腰,滿臉崇拜的說道:死鬼,你不早說,這就夠了?。?!那是什么公司高層?男:我是群主群主燒鍋爐翻樣中國版主7±2原則如果你二,你就關(guān)注7+2件及以上事情【二貨九個圈】如果你不二,你就關(guān)注7-2件及以下事情【不二五個圈】圈復(fù)雜度高的,可以重構(gòu)為如:1.參數(shù)判斷2.取數(shù)據(jù)3.數(shù)據(jù)預(yù)處理4.數(shù)據(jù)轉(zhuǎn)換5.返回數(shù)據(jù)

每一步可以是一個獨立的方法這樣主干邏輯非常的清晰,也就不二金字塔原理:有目標、有層次、有順序總分總結(jié)構(gòu)把大象放冰箱里,統(tǒng)共分幾步?代碼大全25知道做什么嗎?26總共分5步評審、會議常見問題27如果去掉第二層圈復(fù)雜度是。。寫文檔沒有目錄大綱模塊設(shè)計:一個包下N多個類代碼:超大方法超大類圈復(fù)雜度的重構(gòu)控制圈復(fù)雜度的N種重構(gòu)技術(shù)Refactoring:ImprovingtheDesignofExistingCode概念計算方法檢查工具二不二重構(gòu)方法案例分析金字塔原理總分總結(jié)構(gòu)把大象放冰箱里,統(tǒng)共分幾步?金字塔原理寫代碼和寫文章、畫畫總分總結(jié)構(gòu)把大象放冰箱里,統(tǒng)共分幾步?業(yè)務(wù)重構(gòu)架構(gòu)重構(gòu)設(shè)計重構(gòu)代碼重構(gòu)重復(fù)。代碼重復(fù)、結(jié)構(gòu)重復(fù)、邏輯重復(fù)。重復(fù)的代碼是抽象不夠的表現(xiàn)。如果是一個獨立完整的概念,可以提取成一個子程序(抽象)。舉例:多處的排序算法。冗長子程序。如果把子程序的一部分提取來作為另一個獨立的子程序,可以讓代碼更清晰,就提取成子程序。循環(huán)過長或嵌套過深。循環(huán)內(nèi)部的復(fù)雜代碼往往可以轉(zhuǎn)換成子程序。嵌套過深可以用前面“語句”中提過的方法解決。子程序命名不當。需要子程序重命名,或合并、拆分子程序。難懂、拙劣的代碼。需要重整邏輯和流程?!a重構(gòu)重構(gòu)、金字塔原理降低圈復(fù)雜度的方法——重構(gòu)概念重構(gòu)(Refactoring)就是在不改變軟件現(xiàn)有功能的基礎(chǔ)上,通過調(diào)整程序代碼改善軟件的質(zhì)量、性能,使其程序的設(shè)計模式和架構(gòu)更趨合理,提高軟件的擴展性和維護性。重構(gòu)方法重復(fù)代碼或者相似代碼提取為一個新的方法將過長的方法按功能拆分成小的方法將過大類的功能拆分成多個功能單一的小類推薦書籍《重構(gòu)——改善既有代碼的設(shè)計》作者:MartinFowler書中列出了長達70條的重構(gòu)名錄,提供了具體重構(gòu)的方法和重構(gòu)的技巧。將幫助開發(fā)人員一次一小步地修改代碼,減少了開發(fā)過程中的風(fēng)險。Page32可以直接降低圈復(fù)雜度的10種重構(gòu)技術(shù)針對結(jié)構(gòu)化編程:ComposingMethods(重新組織你的函數(shù)) 1.ExtractMethod(提煉函數(shù)) 2.SubstituteAlgorithm(替換你的算法)SimplifyingConditionalExpressions(簡化條件表達式) 3.DecomposeConditional(分解條件式)

4.ConsolidateConditionalExpression(合并條件式)

5.ConsolidateDuplicateConditionalFragments(合并重復(fù)的條件片斷) 6.RemoveControlFlag(移除控制標記)MakingMethodCallsSimpler(簡化函數(shù)調(diào)用) 7.SeparateQueryfromModifier(將查詢函數(shù)和修改函數(shù)分離) 8.ParameterizeMethod(令函數(shù)攜帶參數(shù)) 9.ReplaceParameterwithExplicitMethods(以明確函數(shù)取代參數(shù))

Refactoring:ImprovingtheDesignofExistingCode針對面向?qū)ο缶幊蹋?/p>

10.ReplaceConditionalwithPolymorphism(以多態(tài)取代條件式)控制圈復(fù)雜度的10種重構(gòu)技術(shù)總結(jié)可以直接降低圈復(fù)雜度的9種重構(gòu)技術(shù)(針對結(jié)構(gòu)化編程):*一、ComposingMethods(重新組織你的函數(shù))

1.Extract

Method(提煉函數(shù))

分為不同的step步驟進行處理,主干邏輯方法控制在7個以內(nèi)

將代碼放進一個獨立函數(shù)中,并讓函數(shù)名稱解釋該函數(shù)的用途

2.Substitute

Algorithm(替換你的算法)將函數(shù)本體替換為另一個更清晰、簡化的算法,如多值匹配candidates.contains*二、SimplifyingConditionalExpressions(簡化條件表達式)

3.Decompose

Conditional(分解條件式)

從if、then、else三個段落中分別提煉出獨立函數(shù)

4.Consolidate

ConditionalExpression(合并條件式)

將多個條件合并為c1||c2&&c3,并提煉為一個函數(shù)

5.Consolidate

DuplicateConditionalFragments(合并重復(fù)的條件片斷)

多個條件都執(zhí)行的代碼,將重復(fù)代碼搬移到條件式之外

6.Remove

ControlFlag(移除控制標記)

以break和return取代控制標記

*四、針對面向?qū)ο缶幊蹋?/p>

10.Replace

ConditionalwithPolymorphism(以多態(tài)取代條件式)

將整個條件式的每個分支放進一個子類的重載方法中,然后將原始函數(shù)聲明為抽象方法

面向接口編程,一個接口多種實現(xiàn);利用state模式減少分支*三、MakingMethodCallsSimpler(簡化函數(shù)調(diào)用)

7.Separate

QueryfromModifier(將查詢函數(shù)和修改函數(shù)分離)

單一職責(zé)原則,建立兩個不同的函數(shù),其中一個負責(zé)查詢,另一個負責(zé)修改

8.Parameterize

Method(令函數(shù)攜帶參數(shù))

通用函數(shù),建立單一函數(shù),以參數(shù)表達那些不同的值

9.Replace

ParameterwithExplicitMethods(以明確函數(shù)取代參數(shù))

多個if對應(yīng)對個函數(shù);

針對該參數(shù)的每一個可能值,建立一個獨立函數(shù)

Refactoring:ImprovingtheDesignofExistingCodePage34ExtractMethod(提煉函數(shù))voidprintOwing(doublepreviousAmount){Enumeratione=_orders.elements();doubleoutstanding=previousAmount*1.2;

//printbannerSystem.out.println("**************************");System.out.println("*****CustomerOwes******");System.out.println("**************************");//calculateoutstandingwhile(e.hasMoreElements()){Ordereach=(Order)e.nextElement();outstanding+=each.getAmount();}//printdetailsSystem.out.println("name:"+_name);System.out.println("amount"+outstanding);}voidprintOwing(doublepreviousAmount){printBanner();doubleoutstanding=getOutstanding(previousAmount*1.2);printDetails(outstanding);}voidprintBanner(){//printbannerSystem.out.println("**************************");System.out.println("*****CustomerOwes******");}doublegetOutstanding(doubleinitialValue){doubleresult=initialValue;Enumeratione=_orders.elements();while(e.hasMoreElements()){Ordereach=(Order)e.nextElement();result+=each.getAmount();}returnresult;}voidprintDetails(doubleoutstanding){System.out.println("name:"+_name);System.out.println("amount"+outstanding);}將這段代碼放進一個獨立函數(shù)中,并讓函數(shù)名稱解釋該函數(shù)的用途你有一段代碼可以被組織在一起并獨立出來Page35SubstituteAlgorithm(替換你的算法)StringfoundPerson(String[]people){for(inti=0;i<people.length;i++){if(people[i].equals("Don"))return"Don";if(people[i].equals("John"))return"John";if(people[i].equals("Kent"))return"Kent";}return"";}StringfoundPerson(String[]people){Listcandidates=Arrays.asList(newString[]{"Don","John","Kent"});for(inti=0;i<people.length;i++)if(candidates.contains(people[i]))returnpeople[i];return"";}你想要把某個算法替換為另一個更清晰的算法將函數(shù)本體替換為另一個算法多值判斷用集合多個key,用map【當這個值,調(diào)用某個服務(wù)】多值判斷用集合Page36DecomposeConditional(分解條件式)if(date.before(SUMMER_START)||date.after(SUMMER_END))charge=quantity*_winterRate+_winterServiceCharge;elsecharge=quantity*_summerRate;if(notSummer(date))charge=winterCharge(quantity);elsecharge=summerCharge(quantity);你有一個復(fù)雜的條件語句從if、then、else三個段落中分別提煉出獨立函數(shù)專注、聚焦Page37ConsolidateConditionalExpression(合并條件式)doubledisabilityAmount(){if(_seniority<2)return0;if(_monthsDisabled>12)return0;if(_isPartTime)return0;//computethedisabilityamountdoubledisabilityAmount(){if(isNotEligableForDisability())return0;//computethedisabilityamount將這些判斷合并為一個條件式,并將這個條件式提煉成為一個獨立函數(shù)你有一系列條件判斷,都得到相同結(jié)果Page38ConsolidateDuplicateConditionalFragments(合并重復(fù)的條件片斷)if(isSpecialDeal()){total=price*0.95;send();}else{total=price*0.98;send();}if(isSpecialDeal())total=price*0.95;elsetotal=price*0.98;send();在條件式的每個分支上有著相同的一段代碼。將這段重復(fù)代碼搬移到條件式之外反CVS模式Page39RemoveControlFlag(移除控制標記)voidcheckSecurity(String[]people){booleanfound=false;for(inti=0;i<people.length;i++){if(!found){if(people[i].equals("Don")){sendAlert();found=true;}if(people[i].equals("John")){sendAlert();found=true;}}}}voidcheckSecurity(String[]people){for(inti=0;i<people.length;i++){if(people[i].equals("Don")){sendAlert();break;}if(people[i].equals("John")){sendAlert();break;}}}在一系列布爾表達式種,某個變量帶有【控制標記】的作用以break和return取代控制標記Page40SeparateQueryfromModifier(將查詢函數(shù)和修改函數(shù)分離)某個函數(shù)既返回對象狀態(tài)值,又修改對象狀態(tài)建立兩個不同的函數(shù),其中一個負責(zé)查詢,另一個負責(zé)修改CustomergetTotalOutstandingAndSetReadyForSummariesCustomergetTotalOutstandingSetReadyForSummaries反一心二用、左右互搏Page41ParameterizeMethod(令函數(shù)攜帶參數(shù))DollarsbaseCharge(){doubleresult=Math.min(lastUsage(),100)*0.03;if(lastUsage()>100){result+=(Math.min(lastUsage(),200)-100)*0.05;};if(lastUsage()>200){result+=(lastUsage()-200)*0.07;};returnnewDollars(result);}DollarsbaseCharge(){doubleresult=usageInRange(0,100)*0.03;result+=usageInRange(100,200)*0.05;result+=usageInRange(200,Integer.MAX_VALUE)*0.07;returnnewDollars(result);}intusageInRange(intstart,intend){if(lastUsage()>start)returnMath.min(lastUsage(),end)-start;elsereturn0;}若干函數(shù)做了類似的工作,但在函數(shù)本體中卻包含了不同的值建立單一函數(shù),以參數(shù)表達那些不同的值重構(gòu)為多參函數(shù)Page42ReplaceParameterwithExplicitMethods(以明確函數(shù)取代參數(shù))

voidsetValue(Stringname,intvalue){if(name.equals("height"))_height=value;if(name.equals("width"))_width=value;Assert.shouldNeverReachHere();}voidsetHeight(intarg){_height=arg;}voidsetWidth(intarg){_width=arg;}函數(shù)實現(xiàn)完全取決于參數(shù)值而采取不同反應(yīng)針對該參數(shù)的每一個可能值,建立一個獨立函數(shù)Page43ReplaceConditionalwithPolymorphism(以多態(tài)取代條件式)

doublegetSpeed(){switch(_type){caseEUROPEAN:returngetBaseSpeed();caseAFRICAN:returngetBaseSpeed()-getLoadFactor()*_numberOfCoconuts;caseNORWEGIAN_BLUE:return(_isNailed)?0:getBaseSpeed(_voltage);}thrownewRuntimeException("Shouldbeunreachable");}你手上有個條件式,它根據(jù)對象類型的不同而選擇不同的行為將整個條件式的每個分支放進一個子類的重載方法中,然后將原始函數(shù)聲明為抽象方法面向接口編程利用state模式減少分支

劉翔有三種狀態(tài)三種狀態(tài),生病狀態(tài),正常狀態(tài),興奮狀態(tài)publicvoidrun(){if(state==NORMAL_STATE){//正常狀態(tài)下跑

System.out.println("100米,跑完共用時15秒!");}

elseif(state==MALUM_STATE){//生病狀態(tài)下跑System.out.println("100米,跑完共用時20秒!");

}

elseif(state==EXCITED_STATE){//興奮狀態(tài)下跑

System.out.println("100米,跑完共用時10秒!");}else{System.out.println("未知的狀態(tài)");}}publicinterfaceIState{publicvoiddoRun();}publicclassExcitedStateimplementsIState{publicvoiddoRun(){

System.out.println("100米,跑完共用時10鈔!");}}publicclassMalumStateimplementsIState{

publicvoiddoRun(){System.out.println("100米,跑完共用時20秒!");}}publicclassNormalStateimplementsIState{

publicvoiddoRun(){System.out.println("100米,跑完共用時15秒!");}}采用狀態(tài)模式的運動員publicclassGamer{//當前狀態(tài)

privateIStatestate=newNormalState();//改變狀態(tài)的方法

publicvoidsetState(IStatestate){this.state=state;}//狀態(tài)行為方法,同上面的Gamer類相比這里沒有if..elseif判斷

publicvoidrun(){state.doRun();}}利用state模式減少分支

public

static

void

main(String[]

args)

{

//沒有使用狀態(tài)設(shè)計模式

com.bill99.pattern.Gamer

game

=

new

com.bill99.pattern.Gamer();

game.setState(0);

game.run();

game.setState(1);

game.run();

game.setState(2);

game.run();

System.out.println("");

//使用狀態(tài)設(shè)計模式

//正常狀態(tài)下跑

Gamer

gamer

=

new

Gamer();

gamer.run();

//生病狀態(tài)下跑

gamer.setState(new

MalumState());

gamer.run();

//興奮狀態(tài)下跑

gamer.setState(new

ExcitedState());

gamer.run();

}

SuperExcitedState假如我們再擴展一個超級興奮的狀態(tài)SuperExcitedState,只需實現(xiàn)IState接口,定義好該狀態(tài)的行為,調(diào)用如下gamer.setState(new

SuperExcitedState());gamer.run();如果以后維護的話,要再加一個超級興奮的狀態(tài),得要改原來的源代碼,添加一個代表超級興奮的成員變量,再改if..elseif判斷,這樣做不符合OO設(shè)計原則,實現(xiàn)不了程序的松耦合??刂迫?fù)雜度的10種重構(gòu)技術(shù)總結(jié)可以直接降低圈復(fù)雜度的9種重構(gòu)技術(shù)(針對結(jié)構(gòu)化編程):*一、ComposingMethods(重新組織你的函數(shù))

1.Extract

Method(提煉函數(shù))

分為不同的step步驟進行處理,主干邏輯方法控制在7個以內(nèi)

將代碼放進一個獨立函數(shù)中,并讓函數(shù)名稱解釋該函數(shù)的用途

2.Substitute

Algorithm(替換你的算法)將函數(shù)本體替換為另一個更清晰、簡化的算法,如多值匹配candidates.contains*二、SimplifyingConditionalExpressions(簡化條件表達式)

3.Decompose

Conditional(分解條件式)

從if、then、else三個段落中分別提煉出獨立函數(shù)

4.Consolidate

ConditionalExpression(合并條件式)

將多個條件合并為c1||c2&&c3,并提煉為一個函數(shù)

5.Consolidate

DuplicateConditionalFragments(合并重復(fù)的條件片斷)

多個條件都執(zhí)行的代碼,將重復(fù)代碼搬移到條件式之外

6.Remove

ControlFlag(移除控制標記)

以break和return取代控制標記

*四、針對面向?qū)ο缶幊蹋?/p>

10.Replace

ConditionalwithPolymorphism(以多態(tài)取代條件式)

將整個條件式的每個分支放進一個子類的重載方法中,然后將原始函數(shù)聲明為抽象方法

面向接口編程,一個接口多種實現(xiàn);利用state模式減少分支*三、MakingMethodCallsSimpler(簡化函數(shù)調(diào)用)

7.Separate

QueryfromModifier(將查詢函數(shù)和修改函數(shù)分離)

單一職責(zé)原則,建立兩個不同的函數(shù),其中一個負責(zé)查詢,另一個負責(zé)修改

8.Parameterize

Method(令函數(shù)攜帶參數(shù))

通用函數(shù),建立單一函數(shù),以參數(shù)表達那些不同的值

9.Replace

ParameterwithExplicitMethods(以明確函數(shù)取代參數(shù))

多個if對應(yīng)對個函數(shù);

針對該參數(shù)的每一個可能值,建立一個獨立函數(shù)

Refactoring:ImprovingtheDesignofExistingCode重構(gòu)案例控制圈復(fù)雜度的N種重構(gòu)技術(shù)Refactoring:ImprovingtheDesignofExistingCode概念計算方法檢查工具二不二重構(gòu)方法案例分析代碼生成工具優(yōu)化重構(gòu)前重構(gòu)后1.生成參數(shù)信息2.生成文件內(nèi)容3.寫到文件4.打印日志混亂的代碼是混亂思維的產(chǎn)物上傳文件代碼示例1.不是excel,返回2.超過大小限制,返回3.不滿足條件,返回4.文件內(nèi)容校驗5.多處String類型非空判斷if(StringUtil.isEmpty(username))thrownewICRClientException("usernamecannotbenull");if(StringUtil.isEmpty(password))thrownewICRClientException("passwordcannotbenull");if(udto==null)thrownewICRClientException("ICRUploadDTOcannotbenull");//將原來的地方替換為checkStringParamEmpty(username,"username");checkStringParamEmpty(password,"password");checkStringParamEmpty(udto.getUrlPath(),"urlPath");...//新增一個方法privatevoidcheckStringParamEmpty(Stringvalue,Stringname)throwsICRClientException{if(StringUtil.isEmpty(value)){thrownewICRClientException(name+"cannotbenull");}}多String值判斷if(!udto.getPriority().equals("0")&&!udto.getPriority().equals("1")&&!udto.getPriority().equals("2")&&!udto.getPriority().equals("3"))thrownewICRClientException("prioritymustbe0/1/2/3");//將原來代碼替換為checkValueWithinList(udto.getPriority());...//新增一個方法:privatevoidcheckValueWithinList(Stringpriority)throwsICRClientException{if(!Arrays.asList("0","1","2","3").contains(priority)){thrownewICRClientException("prioritymustbe0/1/2/3");}}多個catch的內(nèi)容相同intcode=0;try{code=httpClient.executeMethod(post);}catch(HttpExceptione){thrownewICRClientException(e.getMessage(),e);}catch(IOExceptione){thrownewICRClientException(e.getMessage(),e);}//將原來的地方替換為intcode=executeHttpClient(httpClient,post);...//新增一個方法privateintexecuteHttpClient(HttpClienthttpClient,PostMethodpost)throwsICRClientException{intcode;try{code=httpClient.executeMethod(post);}catch(Exceptione){thrownewICRClientException(e.getMessage(),e);}returncode;}if判斷結(jié)果復(fù)雜化if(code==200){try{if(post.getResponseBodyAsString().equals("ok")){returntrue;}}catch(IOExceptione){thrownewICRClientException(e.getMessage(),e);}returnfalse;}elseif(code==500){thrownewICRClientException(post.getResponseBodyAsString());}else{thrownewICRClientException(code+":"+post.getStatusText());}returnreturnFinialResult(post,code);...//新增一個方法privatebooleanreturnFinialResult(PostMethodpost,intcode)throwsICRClientException,IOException{if(code==500)thrownewICRClientException(post.getResponseBodyAsString());if(code!=200)thrownewICRClientException(code+":"+post.getStatusText());try{returnpost.getResponseBodyAsString().equals("ok");}catch(IOExceptione){thrownewICRClientException(e.getMessage(),e);}}本地變量始終不為nullpublicbooleanuploadToICR(Stringusername,Stringpassword,ICRUploadDTOudto)throwsICRClientException{HttpClienthttpClient=null;PostMethodpost=null;httpClient=newHttpClient();//somecodehere…}finally{if(post!=null){post.releaseConnection();}if(httpClient!=null){httpClient.getHttpConnectionManager().closeIdleConnections(0);}}publicbooleanuploadToICR(Stringusername,Stringpassword,ICRUploadDTOudto)throwsICRClientException{HttpClienthttpClient=newHttpClient();PostMethodpost=null;//somecodehere…}finally{if(post!=null){post.releaseConnection();}}}讀取IO流的方法,為什么要自己實現(xiàn)?privatebyte[]readData(InputStreamins)throwsIOException{byte[]buf=newbyte[2048];intcount=0;intlen=0;bytedata[]=newbyte[2048];byte[]result=null;try{while((len=ins.read(data,0,2048))!=-1){intnewcount=count+len;if(newcount>buf.length){bytenewbuf[]=newbyte[Math.max(buf.length<<1,newcount)];System.arraycopy(buf,0,newbuf,0,count);buf=newbuf;}System.arraycopy(data,0,buf,count,len);count=newcount;}result=newbyte[count];System.arraycopy(buf,0,result,0,count);}finally{ins.close();}re

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論