好圈復(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ù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、揚(yáng)帆起航圈復(fù)雜度圈復(fù)雜度Cyclomatic Complexity is 17 (max allowed is 7).Cyclomatic Complexity is X (max allowed is X) 我的QQ:28797575知道做什么嗎?文檔示例 無目錄 有目錄不聚焦不知道目標(biāo),不知道總體結(jié)構(gòu)不知道是否合理沒有層次是否有遺漏帶來時(shí)間成本質(zhì)量問題4知道做什么嗎? QQ: 28797575圈復(fù)雜度 概念概念概念計(jì)算方法計(jì)算方法檢查工具檢查工具二二不不二二重構(gòu)方法重構(gòu)方法案例分析案例分析McCabe復(fù)雜度圈復(fù)雜度圈復(fù)雜度基本復(fù)雜度基本復(fù)雜度模塊設(shè)計(jì)復(fù)雜度模塊設(shè)計(jì)復(fù)雜度設(shè)計(jì)復(fù)雜度設(shè)計(jì)復(fù)雜度

2、集成復(fù)雜度集成復(fù)雜度行數(shù)行數(shù)全局?jǐn)?shù)據(jù)復(fù)雜度全局?jǐn)?shù)據(jù)復(fù)雜度局部數(shù)據(jù)復(fù)雜度局部數(shù)據(jù)復(fù)雜度病態(tài)數(shù)據(jù)復(fù)雜度病態(tài)數(shù)據(jù)復(fù)雜度規(guī)范化復(fù)雜度規(guī)范化復(fù)雜度框架群:181124238 我的QQ:307087558(1)圈復(fù)雜度(Cyclomatic Complexity (v(G) )l概念圈復(fù)雜度是用來衡量一個(gè)模塊判定結(jié)構(gòu)的復(fù)雜程度,數(shù)量上表現(xiàn)為獨(dú)立路徑的條數(shù)。l計(jì)算方法如果一個(gè)模塊流程圖有e條邊n個(gè)節(jié)點(diǎn), 它的圈復(fù)雜度v(G)=e-n+2。 QQ: 28797575 圈復(fù)雜度(Cyclomatic Complexity)是一種代碼復(fù)雜度的衡量標(biāo)準(zhǔn)。它可以用來衡量一個(gè)模塊判定結(jié)構(gòu)的復(fù)雜程度,數(shù)量上表現(xiàn)為獨(dú)立線性

3、路徑條數(shù),也可理解為覆蓋所有的可能情況最少使用的測(cè)試用例數(shù)。圈復(fù)雜度大說明程序代碼的判斷邏輯復(fù)雜,可能質(zhì)量低且難于測(cè)試和維護(hù)。程序的可能錯(cuò)誤和高的圈復(fù)雜度有著很大關(guān)系。 圈復(fù)雜度主要與分支語句(if、else、switch 、for等)的個(gè)數(shù)成正相關(guān)。當(dāng)一段代碼中含有較多的分支語句,其邏輯復(fù)雜程度就會(huì)增加。什么是圈復(fù)雜度 QQ: 28797575示例下面這個(gè)實(shí)例中,單元測(cè)試的覆蓋率可以達(dá)到100%,但是很容易發(fā)現(xiàn)這其中已經(jīng)漏掉了一個(gè)NPE的測(cè)試用例。case1方法的圈復(fù)雜度為2,因此至少需要2個(gè)用例才能完全覆蓋到其所有的可能情況。/程序原代碼,圈復(fù)雜度為 2public String case

4、1(int num) String string = null; if (num = 1) string = String; return string.substring(0);/上面代碼的單元測(cè)試代碼public void testCase1() String test1 = case1(1); 圈復(fù)雜度主要與分支語句(if、else、,switch 等)的個(gè)數(shù)成正相關(guān)。當(dāng)一段代碼中含有較多的分支語句,其邏輯復(fù)雜程度就會(huì)增加。 QQ: QQ: 28797575圈復(fù)雜度 計(jì)算概念概念計(jì)算方法計(jì)算方法檢查工具檢查工具二不二二不二重構(gòu)方法重構(gòu)方法案例分析案例分析 QQ: 28797575示例 如

5、果一個(gè)模塊流程如下有e條邊n個(gè)節(jié)點(diǎn),它的圈復(fù)雜度v(G) = e-n+2 例: QQ: 28797575圈復(fù)雜度的計(jì)算 圈復(fù)雜度(cyclomatic complexity): M = E N + 2P E: 邊的數(shù)量 N: 節(jié)點(diǎn)的數(shù)量 P: 分離部分的數(shù)量,一般為1,都是聯(lián)通的 圈數(shù)(cyclomatic number): M = E N + P E,N,P參數(shù)同上 圈復(fù)雜度和圈數(shù)之間的關(guān)系為: 對(duì)有向圖A,將A的每個(gè)出口(exit)與相應(yīng)的入口(entrance)相連得到有向圖B,則A的圈復(fù)雜度與B的圈數(shù)相等 圈復(fù)雜度又叫做CC復(fù)雜度,也可能被稱為循環(huán)復(fù)雜度,它表達(dá)的是if . then

6、. else ., swith . case ., 循環(huán)語句等分支語句造成的程序控制流復(fù)雜程度 QQ: 28797575計(jì)算公式補(bǔ)充 通常使用的計(jì)算公式是V(G) = e n + 2 , e 代表在控制流圖中的邊的數(shù)量(對(duì)應(yīng)代碼中順序結(jié)構(gòu)的部分),n 代表在控制流圖中的節(jié)點(diǎn)數(shù)量,包括起點(diǎn)和終點(diǎn)(1、所有終點(diǎn)只計(jì)算一次,即便有多個(gè)return或者throw;2、節(jié)點(diǎn)對(duì)應(yīng)代碼中的分支語句)。 QQ: 28797575 例如下圖示例一個(gè)單入口、單出口的程序圖(不是結(jié)構(gòu)化程序圖),其圈復(fù)雜度為10-7+2=5: 從節(jié)點(diǎn)G到A添加一條有向邊,則成為一個(gè)強(qiáng)連通有向圖(該方法對(duì)其它結(jié)構(gòu)化程序圖同樣適用),其

7、圈數(shù)為11-7+1=5,與上圖的圈復(fù)雜度相同: QQ: 28797575計(jì)算示例 public String case2(int index, String string) String returnString = 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(

8、) 2 ); return returnString; QQ: 28797575 根據(jù)公式 V(G) = e n + 2 = 12 8 + 2 = 6 。case2的圈復(fù)雜段為6。說明一下為什么n = 8,雖然圖上的真正節(jié)點(diǎn)有12個(gè),但是其中有5個(gè)節(jié)點(diǎn)為throw、return,這樣的節(jié)點(diǎn)為end節(jié)點(diǎn),只能記做一個(gè)。計(jì)算示例檢查工具概念概念計(jì)算計(jì)算檢查工具檢查工具二二不不二二重構(gòu)重構(gòu) QQ: 28797575檢查工具 開發(fā)中常用的檢測(cè)圈復(fù)雜度的工具,PMD,checkstyle都可以檢測(cè)到高復(fù)雜度的代碼塊 Eclipse Metric 插件:有效地查出復(fù)雜度 JavaNCSS NCSS表示No

9、n Commenting Source S QQ: 28797575工具工具目的目的Eclipse 插件的插件的 URLCheckStyle編碼標(biāo)準(zhǔn)分析http:/eclipse- QQ: 28797575直接管好幾百人女:有三室兩廳嗎?男:沒有 女:有路虎,奧迪嗎? 男:沒有! 女:有7位數(shù)存款嗎(? 男:沒有+! 女:那你有啥? 男:我 女轉(zhuǎn)身就走,。 突然男的說:我管理幾百人(。 女立刻回頭抱住男的腰,滿臉崇拜的說道:死鬼,你不早說,這就夠了!那是什么公司高層? 男:我是群主群主燒鍋爐翻樣中國版主 QQ: 2879757572原則如果你二,你就關(guān)注7+2件及以上事情【二貨九個(gè)圈】如果你不

10、二,你就關(guān)注7-2件及以下事情【不二五個(gè)圈】圈復(fù)雜度高的,可以重構(gòu)為如:1.參數(shù)判斷2.取數(shù)據(jù)3.數(shù)據(jù)預(yù)處理4.數(shù)據(jù)轉(zhuǎn)換5.返回?cái)?shù)據(jù)每一步可以是一個(gè)獨(dú)立的方法這樣主干邏輯非常的清晰,也就不二金字塔金字塔原理:有目標(biāo)、有層次、有順序原理:有目標(biāo)、有層次、有順序總分總結(jié)構(gòu)總分總結(jié)構(gòu)把大象放冰箱里,統(tǒng)共分幾步?把大象放冰箱里,統(tǒng)共分幾步? QQ: 28797575代碼大全25知道做什么嗎?26總總共共分分5步步評(píng)審、會(huì)議常見問題27如果去掉第二層如果去掉第二層圈復(fù)雜度是。圈復(fù)雜度是。 QQ: 28797575寫文檔沒有目錄大綱模塊設(shè)計(jì):一個(gè)包下N多個(gè)類代碼:超大方法超大類圈復(fù)雜度的重構(gòu)控制圈復(fù)雜度的

11、N種重構(gòu)技術(shù)-Refactoring: Improving the Design of Existing Code概念概念計(jì)算方法計(jì)算方法檢查工具檢查工具二不二二不二重構(gòu)方法重構(gòu)方法案例分析案例分析金字塔原理金字塔原理總分總結(jié)構(gòu)總分總結(jié)構(gòu)把大象放冰箱里,統(tǒng)共分幾步?把大象放冰箱里,統(tǒng)共分幾步?金字塔原理金字塔原理 寫代碼和寫文章、畫畫寫代碼和寫文章、畫畫總分總結(jié)構(gòu)總分總結(jié)構(gòu)把大象放冰箱里,統(tǒng)共分幾步?把大象放冰箱里,統(tǒng)共分幾步?業(yè)務(wù)重構(gòu)業(yè)務(wù)重構(gòu)架構(gòu)重構(gòu)架構(gòu)重構(gòu)設(shè)計(jì)重構(gòu)設(shè)計(jì)重構(gòu)代碼重構(gòu)代碼重構(gòu)重復(fù)重復(fù)。代碼重復(fù)、結(jié)構(gòu)重復(fù)、邏輯重復(fù)。重復(fù)的代碼是抽象不夠的表現(xiàn)。如果是一個(gè)獨(dú)立完整的概念,可以提取成

12、一個(gè)子程序(抽象)。舉例:多處的排序算法。冗長子程序冗長子程序。如果把子程序的一部分提取來作為另一個(gè)獨(dú)立的子程序,可以讓代碼更清晰,就提取成子程序。循環(huán)過長或嵌套過深循環(huán)過長或嵌套過深。循環(huán)內(nèi)部的復(fù)雜代碼往往可以轉(zhuǎn)換成子程序。嵌套過深可以用前面“語句”中提過的方法解決。子程序命名不當(dāng)子程序命名不當(dāng)。需要子程序重命名,或合并、拆分子程序。難懂、拙劣的代碼難懂、拙劣的代碼。需要重整邏輯和流程。代碼重構(gòu)代碼重構(gòu)降低圈復(fù)雜度的方法重構(gòu)l 概念 重構(gòu)(Refactoring)就是在不改變軟件現(xiàn)有功能的基礎(chǔ)上,通過調(diào)整程序代碼改善軟件的質(zhì)量、性能,使其程序的設(shè)計(jì)模式和架構(gòu)更趨合理,提高軟件的擴(kuò)展性和維護(hù)性

13、。l 重構(gòu)方法 重復(fù)代碼或者相似代碼提取為一個(gè)新的方法 將過長的方法按功能拆分成小的方法 將過大類的功能拆分成多個(gè)功能單一的小類l 推薦書籍 重構(gòu)改善既有代碼的設(shè)計(jì) 作者:Martin Fowler 書中列出了長達(dá)70條的重構(gòu)名錄,提供了具體重構(gòu)的方法和重構(gòu)的技巧。將幫助開發(fā)人員一次一小步地修改代碼,減少了開發(fā)過程中的風(fēng)險(xiǎn)。 QQ: 28797575Page 32可以直接降低圈復(fù)雜度的10種重構(gòu)技術(shù)針對(duì)結(jié)構(gòu)化編程:Composing Methods(重新組織你的函數(shù))1.Extract Method(提煉函數(shù))2.Substitute Algorithm(替換你的算法)Simplifying

14、Conditional Expressions(簡化條件表達(dá)式)3.Decompose Conditional(分解條件式)4.Consolidate Conditional Expression(合并條件式)5.Consolidate Duplicate Conditional Fragments(合并重復(fù)的條件片斷)6.Remove Control Flag(移除控制標(biāo)記)Making Method Calls Simpler(簡化函數(shù)調(diào)用)7.Separate Query from Modifier(將查詢函數(shù)和修改函數(shù)分離)8.Parameterize Method(令函數(shù)攜帶參數(shù))9

15、.Replace Parameter with Explicit Methods(以明確函數(shù)取代參數(shù))- Refactoring: Improving the Design of Existing Code針對(duì)面向?qū)ο缶幊蹋?0.Replace Conditional with Polymorphism(以多態(tài)取代條件式)控制圈復(fù)雜度的10種重構(gòu)技術(shù)總結(jié)可以直接降低圈復(fù)雜度的9種重構(gòu)技術(shù)(針對(duì)結(jié)構(gòu)化編程):*一、Composing Methods(重新組織你的函數(shù)) 1.Extract Method(提煉函數(shù)) 分為不同的step步驟進(jìn)行處理,主干邏輯方法控制在7個(gè)以內(nèi) 將代碼放進(jìn)一個(gè)獨(dú)立函數(shù)

16、中,并讓函數(shù)名稱解釋該函數(shù)的用途 2.Substitute Algorithm(替換你的算法) 將函數(shù)本體替換為另一個(gè)更清晰、簡化的算法 ,如多值匹配 candidates.contains*二、Simplifying Conditional Expressions(簡化條件表達(dá)式) 3.Decompose Conditional(分解條件式) 從if、then、else三個(gè)段落中分別提煉出獨(dú)立函數(shù) 4.Consolidate Conditional Expression(合并條件式) 將多個(gè)條件合并 為 c1|c2&c3,并提煉為一個(gè)函數(shù) 5.Consolidate Duplicat

17、e Conditional Fragments(合并重復(fù)的條件片斷) 多個(gè)條件都執(zhí)行的代碼,將重復(fù)代碼搬移到條件式之外 6.Remove Control Flag(移除控制標(biāo)記) 以break和return取代控制標(biāo)記* 10.Replace Conditional with Polymorphism(以多態(tài)?。ㄒ远鄳B(tài)取代條件式)代條件式) 將整個(gè)條件式的每個(gè)分支放進(jìn)一個(gè)子類的重載方法將整個(gè)條件式的每個(gè)分支放進(jìn)一個(gè)子類的重載方法中,然后將原始函數(shù)聲明為抽象方法中,然后將原始函數(shù)聲明為抽象方法 面向接口編程,一個(gè)接口多種實(shí)現(xiàn);利用state模式減少分支*三三、Making Method Call

18、s Simpler(簡化函數(shù)調(diào)用)(簡化函數(shù)調(diào)用) 7.Separate Query from Modifier(將查詢函數(shù)和修改函數(shù)分(將查詢函數(shù)和修改函數(shù)分離)離) 單一職責(zé)原則,建立兩個(gè)不同的函數(shù),其中一個(gè)負(fù)責(zé)查建立兩個(gè)不同的函數(shù),其中一個(gè)負(fù)責(zé)查詢,另一個(gè)負(fù)責(zé)修改詢,另一個(gè)負(fù)責(zé)修改 8.Parameterize Method(令函數(shù)攜帶參數(shù))(令函數(shù)攜帶參數(shù)) 通用函數(shù),建立單一函數(shù),以參數(shù)表達(dá)那些不同的值建立單一函數(shù),以參數(shù)表達(dá)那些不同的值 9.Replace Parameter with Explicit Methods(以明確函數(shù)?。ㄒ悦鞔_函數(shù)取代參數(shù))代參數(shù)) 多個(gè)if對(duì)應(yīng)對(duì)個(gè)函

19、數(shù); 針對(duì)該參數(shù)的每一個(gè)可能值,建立針對(duì)該參數(shù)的每一個(gè)可能值,建立一個(gè)獨(dú)立函數(shù)一個(gè)獨(dú)立函數(shù) - Refactoring: Improving the Design of Existing CodePage 34Extract Method(提煉函數(shù))void printOwing(double previousAmount) Enumeration e = _orders.elements(); double outstanding = previousAmount * 1.2; / print banner System.out.println (*); System.out.println

20、 (* Customer Owes *); System.out.println (*); / calculate outstanding while (e.hasMoreElements() Order each = (Order) e.nextElement(); outstanding += each.getAmount(); /print details System.out.println (name: + _name); System.out.println (amount + outstanding);void printOwing(double previousAmount)

21、printBanner(); double outstanding = getOutstanding(previousAmount * 1.2); printDetails(outstanding);void printBanner() / print banner System.out.println (*); System.out.println (* Customer Owes *);double getOutstanding(double initialValue) double result = initialValue; Enumeration e = _orders.elemen

22、ts(); while (e.hasMoreElements() Order each = (Order) e.nextElement(); result += each.getAmount(); return result;void printDetails (double outstanding) System.out.println (name: + _name); System.out.println (amount + outstanding);將這段代碼放進(jìn)一個(gè)獨(dú)立函數(shù)中,將這段代碼放進(jìn)一個(gè)獨(dú)立函數(shù)中,并讓函數(shù)名稱解釋該函數(shù)的用途并讓函數(shù)名稱解釋該函數(shù)的用途你有一段代碼可以被組織在

23、一起并獨(dú)立出來Page 35Substitute Algorithm(替換你的算法)String foundPerson(String people) for (int i = 0; i people.length; i+) if (peoplei.equals (Don) return Don; if (peoplei.equals (John) return John; if (peoplei.equals (Kent) return Kent; return ;String foundPerson(String people) List candidates = Arrays.asLis

24、t(new StringDon, John,Kent); for (int i=0; ipeople.length; i+) if (candidates.contains(peoplei) return peoplei; return ;你想要把某個(gè)算法替換為另一個(gè)更清晰的算法將函數(shù)本體替換為另一個(gè)算法多值判斷用集合多個(gè)key,用map【當(dāng)這個(gè)值,調(diào)用某個(gè)服務(wù)】多值判斷用集合Page 36Decompose Conditional(分解條件式)if (date.before (SUMMER_START) | date.after(SUMMER_END) charge = quantity *

25、 _winterRate + _winterServiceCharge;else charge = quantity * _summerRate;if (notSummer(date) charge = winterCharge(quantity);else charge = summerCharge (quantity);你有一個(gè)復(fù)雜的條件語句從從if、then、else三個(gè)段落中分別提煉出獨(dú)立函數(shù)三個(gè)段落中分別提煉出獨(dú)立函數(shù)專注、聚焦專注、聚焦Page 37Consolidate Conditional Expression(合并條件式)double disabilityAmount()

26、if (_seniority 12) return 0; if (_isPartTime) return 0; / compute the disability amountdouble disabilityAmount() if (isNotEligableForDisability() return 0; / compute the disability amount將這些判斷合并為一個(gè)條件式,并將這個(gè)條件式提煉成為一個(gè)獨(dú)立函數(shù)將這些判斷合并為一個(gè)條件式,并將這個(gè)條件式提煉成為一個(gè)獨(dú)立函數(shù)你有一系列條件判斷,都得到相同結(jié)果Page 38Consolidate Duplicate Condi

27、tional Fragments(合并重復(fù)的條件片斷)if (isSpecialDeal() total = price * 0.95; send(); else total = price * 0.98; send(); if (isSpecialDeal() total = price * 0.95;else total = price * 0.98;send();在條件式的每個(gè)分支上有著相同的一段代碼。將這段重復(fù)代碼搬移到條件式之外將這段重復(fù)代碼搬移到條件式之外反反CVS模式模式Page 39Remove Control Flag(移除控制標(biāo)記)void checkSecurity(St

28、ring people) boolean found = false; for (int i = 0; i people.length; i+) if (! found) if (peoplei.equals (Don) sendAlert(); found = true; if (peoplei.equals (John) sendAlert(); found = true; void checkSecurity(String people) for (int i = 0; i 100) result += (Math.min (lastUsage(),200) - 100) * 0.05;

29、 ; if (lastUsage() 200) result += (lastUsage() - 200) * 0.07; ; return new Dollars (result);Dollars baseCharge() double result = usageInRange(0, 100) * 0.03; result += usageInRange (100,200) * 0.05; result += usageInRange (200, Integer.MAX_VALUE) * 0.07; return new Dollars (result);int usageInRange(

30、int start, int end) if (lastUsage() start) return Math.min(lastUsage(),end) -start; else return 0;若干函數(shù)做了類似的工作,但在函數(shù)本體中卻包含了不同的值建立單一函數(shù),以參數(shù)表達(dá)那些不同的值建立單一函數(shù),以參數(shù)表達(dá)那些不同的值重構(gòu)為多參函數(shù)重構(gòu)為多參函數(shù)Page 42Replace Parameter with Explicit Methods(以明確函數(shù)取代參數(shù))void setValue (String name, int value) if (name.equals(height) _heig

31、ht = value; if (name.equals(width) _width = value; Assert.shouldNeverReachHere();void setHeight(int arg) _height = arg;void setWidth (int arg) _width = arg;函數(shù)實(shí)現(xiàn)完全取決于參數(shù)值而采取不同反應(yīng)針對(duì)該參數(shù)的每一個(gè)可能值,建立一個(gè)獨(dú)立函數(shù)針對(duì)該參數(shù)的每一個(gè)可能值,建立一個(gè)獨(dú)立函數(shù)Page 43Replace Conditional with Polymorphism(以多態(tài)取代條件式)double getSpeed() switch (_ty

32、pe) case EUROPEAN: return getBaseSpeed(); case AFRICAN: return getBaseSpeed() - getLoadFactor() *_numberOfCoconuts; case NORWEGIAN_BLUE: return (_isNailed) ? 0 : getBaseSpeed(_voltage); throw new RuntimeException (Should be unreachable);你手上有個(gè)條件式,它根據(jù)對(duì)象類型的不同而選擇不同的行為將整個(gè)條件式的每個(gè)分支放進(jìn)一個(gè)子類的重載方法中,然后將原始函數(shù)聲明為抽象

33、方法將整個(gè)條件式的每個(gè)分支放進(jìn)一個(gè)子類的重載方法中,然后將原始函數(shù)聲明為抽象方法+getSpeed()BirdBird+getSpeed()EuropeanEuropean+getSpeed()AfricanAfrican+getSpeed()Norwegian BlueNorwegian Blue面向接口編程面向接口編程利用state模式減少分支 劉翔有三種狀態(tài)三種狀態(tài),生病狀態(tài),正常狀態(tài),興奮狀態(tài)public void run() if(state = NORMAL_STATE) /正常狀態(tài)下跑 System.out.println(100米,跑完共用時(shí)15秒!); else if(sta

34、te = MALUM_STATE) /生病狀態(tài)下跑 System.out.println(100米,跑完共用時(shí)20秒!); else if(state = EXCITED_STATE) /興奮狀態(tài)下跑 System.out.println(100米,跑完共用時(shí)10秒!); else System.out.println(未知的狀態(tài));public interface IState public void doRun(); public class ExcitedState implements IState public void doRun() System.out.println(100米

35、,跑完共用時(shí)10鈔!); public class MalumState implements IState public void doRun() System.out.println(100米,跑完共用時(shí)20秒!); public class NormalState implements IState public void doRun() System.out.println(100米,跑完共用時(shí)15秒!); 采用狀態(tài)模式的運(yùn)動(dòng)員public class Gamer /當(dāng)前狀態(tài) private IState state = new NormalState(); /改變狀態(tài)的方法 publ

36、ic void setState(IState state) this.state = state; /狀態(tài)行為方法,同上面的Gamer 類相比這里沒有if.else if判斷 public void run() state.doRun(); 利用state模式減少分支 public static void main(String args) /沒有使用狀態(tài)設(shè)計(jì)模式 com.bill99.pattern.Gamer game = new com.bill99.pattern.Gamer(); game.setState(0); game.run(); game.setState(1); gam

37、e.run(); game.setState(2); game.run(); System.out.println(-); /使用狀態(tài)設(shè)計(jì)模式 /正常狀態(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假如我們?cè)贁U(kuò)展一個(gè)超級(jí)興奮的狀態(tài)SuperExcitedState,只需實(shí)現(xiàn)IState接口,定義好該狀態(tài)

38、的行為,調(diào)用如下gamer.setState(new SuperExcitedState();gamer.run();如果以后維護(hù)的話,要再加一個(gè)超級(jí)興奮的狀態(tài),得要改原來的源代碼,添加一個(gè)代表超級(jí)興奮的成員變量,再改if.else if判斷,這樣做不符合OO設(shè)計(jì)原則,實(shí)現(xiàn)不了程序的松耦合。控制圈復(fù)雜度的10種重構(gòu)技術(shù)總結(jié)可以直接降低圈復(fù)雜度的9種重構(gòu)技術(shù)(針對(duì)結(jié)構(gòu)化編程):*一、Composing Methods(重新組織你的函數(shù)) 1.Extract Method(提煉函數(shù)) 分為不同的step步驟進(jìn)行處理,主干邏輯方法控制在7個(gè)以內(nèi) 將代碼放進(jìn)一個(gè)獨(dú)立函數(shù)中,并讓函數(shù)名稱解釋該函數(shù)的用途

39、 2.Substitute Algorithm(替換你的算法) 將函數(shù)本體替換為另一個(gè)更清晰、簡化的算法 ,如多值匹配 candidates.contains*二、Simplifying Conditional Expressions(簡化條件表達(dá)式) 3.Decompose Conditional(分解條件式) 從if、then、else三個(gè)段落中分別提煉出獨(dú)立函數(shù) 4.Consolidate Conditional Expression(合并條件式) 將多個(gè)條件合并 為 c1|c2&c3,并提煉為一個(gè)函數(shù) 5.Consolidate Duplicate Conditional Fr

40、agments(合并重復(fù)的條件片斷) 多個(gè)條件都執(zhí)行的代碼,將重復(fù)代碼搬移到條件式之外 6.Remove Control Flag(移除控制標(biāo)記) 以break和return取代控制標(biāo)記* 10.Replace Conditional with Polymorphism(以多態(tài)?。ㄒ远鄳B(tài)取代條件式)代條件式) 將整個(gè)條件式的每個(gè)分支放進(jìn)一個(gè)子類的重載方法將整個(gè)條件式的每個(gè)分支放進(jìn)一個(gè)子類的重載方法中,然后將原始函數(shù)聲明為抽象方法中,然后將原始函數(shù)聲明為抽象方法 面向接口編程,一個(gè)接口多種實(shí)現(xiàn);利用state模式減少分支*三三、Making Method Calls Simpler(簡化函數(shù)調(diào)用

41、)(簡化函數(shù)調(diào)用) 7.Separate Query from Modifier(將查詢函數(shù)和修改函數(shù)分(將查詢函數(shù)和修改函數(shù)分離)離) 單一職責(zé)原則,建立兩個(gè)不同的函數(shù),其中一個(gè)負(fù)責(zé)查建立兩個(gè)不同的函數(shù),其中一個(gè)負(fù)責(zé)查詢,另一個(gè)負(fù)責(zé)修改詢,另一個(gè)負(fù)責(zé)修改 8.Parameterize Method(令函數(shù)攜帶參數(shù))(令函數(shù)攜帶參數(shù)) 通用函數(shù),建立單一函數(shù),以參數(shù)表達(dá)那些不同的值建立單一函數(shù),以參數(shù)表達(dá)那些不同的值 9.Replace Parameter with Explicit Methods(以明確函數(shù)?。ㄒ悦鞔_函數(shù)取代參數(shù))代參數(shù)) 多個(gè)if對(duì)應(yīng)對(duì)個(gè)函數(shù); 針對(duì)該參數(shù)的每一個(gè)可能值,

42、建立針對(duì)該參數(shù)的每一個(gè)可能值,建立一個(gè)獨(dú)立函數(shù)一個(gè)獨(dú)立函數(shù) - Refactoring: Improving the Design of Existing Code重構(gòu)案例控制圈復(fù)雜度的N種重構(gòu)技術(shù)-Refactoring: Improving the Design of Existing Code概念概念計(jì)算方法計(jì)算方法檢查工具檢查工具二不二二不二重構(gòu)方法重構(gòu)方法案例分析案例分析代碼生成工具優(yōu)化重構(gòu)前重構(gòu)后1.生成參數(shù)信息生成參數(shù)信息2.生成文件內(nèi)容生成文件內(nèi)容3.寫到文件寫到文件4.打印日志打印日志混亂的代碼是混亂思維的產(chǎn)物上傳文件代碼示例1.不是不是excel,返回,返回2.超過大小限制

43、,返回超過大小限制,返回3.不滿足條件,返回不滿足條件,返回4.文件內(nèi)容校驗(yàn)文件內(nèi)容校驗(yàn)5.多處String類型非空判斷if (StringUtil.isEmpty(username) throw new ICRClientException(username can not be null);if (StringUtil.isEmpty(password) throw new ICRClientException(password can not be null);if (udto = null) throw new ICRClientException(ICRUploadDTO can n

44、ot be null);/將原來的地方替換為checkStringParamEmpty(username, username);checkStringParamEmpty(password, password);checkStringParamEmpty(udto.getUrlPath(), urlPath);./新增一個(gè)方法private void checkStringParamEmpty(String value, String name) throws ICRClientException if (StringUtil.isEmpty(value) throw new ICRClien

45、tException(name + can not be null); 多String值判斷if (!udto.getPriority().equals(0) & !udto.getPriority().equals(1) & !udto.getPriority().equals(2) & !udto.getPriority().equals(3)throw new ICRClientException(priority must be 0/1/2/3);/將原來代碼替換為checkValueWithinList(udto.getPriority();./新增一個(gè)方法:

46、private void checkValueWithinList(String priority) throws ICRClientException if (!Arrays.asList(0, 1, 2, 3).contains(priority) throw new ICRClientException(priority must be 0/1/2/3); 多個(gè)catch的內(nèi)容相同int code = 0;try code = httpClient.executeMethod(post); catch (HttpException e) throw new ICRClientExcept

47、ion(e.getMessage(), e); catch (IOException e) throw new ICRClientException(e.getMessage(), e);/將原來的地方替換為int code = executeHttpClient(httpClient, post);./新增一個(gè)方法private int executeHttpClient(HttpClient httpClient, PostMethod post) throws ICRClientException int code; try code = httpClient.executeMethod

48、(post); catch (Exception e) throw new ICRClientException(e.getMessage(), e); return code;if判斷結(jié)果復(fù)雜化 if (code = 200) try if (post.getResponseBodyAsString().equals(ok) return true; catch (IOException e) throw new ICRClientException(e.getMessage(), e); return false; else if (code = 500) throw new ICRCli

49、entException(post.getResponseBodyAsString(); else throw new ICRClientException(code + : + post.getStatusText();return returnFinialResult(post, code);./新增一個(gè)方法private boolean returnFinialResult(PostMethod post, int code) throws ICRClientException, IOException if (code = 500) throw new ICRClientExcepti

50、on(post.getResponseBodyAsString(); if (code != 200) throw new ICRClientException(code + : + post.getStatusText(); try return post.getResponseBodyAsString().equals(ok); catch (IOException e) throw new ICRClientException(e.getMessage(), e); 本地變量始終不為nullpublic boolean uploadToICR(String username, Strin

51、g password, ICRUploadDTO udto) throws ICRClientException HttpClient httpClient = null; PostMethod post = null; httpClient = new HttpClient(); /some code here finally if (post != null) post.releaseConnection(); if (httpClient != null) httpClient.getHttpConnectionManager().closeIdleConnections(0); pub

52、lic boolean uploadToICR(String username, String password, ICRUploadDTO udto) throws ICRClientException HttpClient httpClient = new HttpClient(); PostMethod post = null; /some code here finally if (post != null) post.releaseConnection(); 讀取IO流的方法,為什么要自己實(shí)現(xiàn)?private byte readData(InputStream ins) throws

53、 IOException byte buf = new byte2048; int count = 0; int len = 0; byte data = new byte2048; byte result = null; try while (len = ins.read(data, 0, 2048) != -1) int newcount = count + len; if (newcount buf.length) byte newbuf = new byteMath .max(buf.length 1, newcount); System.arraycopy(buf, 0, newbu

54、f, 0, count); buf = newbuf; System.arraycopy(data, 0, buf, count, len); count = newcount; result = new bytecount; System.arraycopy(buf, 0, result, 0, count); finally ins.close(); return result;/使用apache io API的實(shí)現(xiàn): byte bytes = IOUtils.toByteArray(inputStream); /使用guava API的實(shí)現(xiàn): byte bytes1 = ByteStreams.toByteArray(inputStream);持續(xù)重構(gòu)重構(gòu)要盡早且要經(jīng)常進(jìn)行太多導(dǎo)入表明一個(gè)類過多地依賴于其他的類。您會(huì)注意到,由于一個(gè)類與很多其他的類耦合得太緊密,修改這個(gè)類會(huì)導(dǎo)致必須對(duì)很多其他的類進(jìn)行修改,這時(shí)就說明

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論