版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、追求代碼質量(2):監(jiān)視圈復雜度-編程 開發(fā)技術追求代碼質量(2)監(jiān)視圈復雜度原文出處:ibm中國每位開發(fā)人員對代碼質量的含義都冇著自己的看法,并且大多數(shù)人對如何查找編 寫欠佳的代碼也有口己的想法。甚至術語代碼味道(code smell) ?也已進入大 眾詞匯表,成為描述代碼需耍改進的一種方式。代碼味道通常由開發(fā)人員直接判定,有趣的是,它是許多代碼注釋綜合在一起的 味道。一些人聲稱公正的代碼注釋是好事情,而另一些人聲稱代碼注釋只是解釋 過于復雜的代碼的一種機制。顯然,javadocs?很有用,但是多少內嵌注釋才足 以維護代碼?如果代碼已經(jīng)編寫得足夠好,它述需要解釋自己嗎?這告訴我們,代碼味道是
2、一種評估代碼的機制,它具冇主觀性。我相信,那些聞 起來味道糟透了的代碼可能是其他人曾經(jīng)編寫的最好的代碼。以下這些短語聽起 來是不是很熟悉?是的,它初看起來冇點亂,但是您要看到它多么可擴展!或者它讓您感到迷惑,但顯然您不了解它的模式。我們需要的是客觀評估代碼質量的方法,某種可以決定性地告訴我們正在查看的 代碼是否存在風險的東西。不管您是否相信,這種東西確實存在!用來客觀評佔 代碼質量的機制已經(jīng)出現(xiàn)了一段時間了,只是大多數(shù)開發(fā)人員忽略了它們。這些 機制被稱為代碼度量(code metric)。代碼度量的歷史幾十年前,少數(shù)幾個非常聰明的人開始研究代碼,希望定義一個能夠與缺陷關聯(lián) 的測量系統(tǒng)。這是一個
3、非常有趣的主張:通過研究帶bug代碼中的模式,他們 希望創(chuàng)建止式的模型,然后可以評估這些模型,在缺陷成為缺陷捕獲它們。在這條研究z路上,其他一些非常聰明的人也決定通過研究代碼看看他們是否可 以測量開發(fā)人員的生產效率。對每位開發(fā)人員的代碼行的經(jīng)典度量似乎只停留在 表面上:joe生產的代碼要比bill多,因此joe生產率更高一些,值得 我們花錢聘請這樣的人。此外,我注意到b訂1經(jīng)常在飲水機邊閑 黒我認為我們應該解雇bill。但是這種生產率度量在實踐屮是非常令人失望的,主要是因為它容易被濫用。一 些代碼測量包描內嵌注釋,并且這種度量實際上受益于剪切粘貼式開發(fā) (cut-and-paste style
4、 development)。joe編寫了許多缺陷!其他每條缺陷也都是由他間接造成的。我們 不該解雇b訂1,他的代碼實際上是免檢的??梢灶A見,生產率研究被證實是非常不準確的,但在管理團隊(mariagcrncrit body) 廣泛使用這種生產率度量以期了解每個人的能力的價值z前,情況并非如此。來 自開發(fā)人員社區(qū)的痛苦反應是有理由的,對于一些人而言,那種痛苦感覺從未真 正走遠。未經(jīng)雕琢的鉆石盡管存在這些失敗,但在那些復雜度與缺陷的相互關系的研究屮仍然有一些美 玉。大多數(shù)開發(fā)人員忘記進行代碼質量研究已有很長一段時間了,但對于那些仍 正在鉆研的人而言(特別是如果您也正在為追求代碼質量而努力鉆研),會
5、在今 天的應用中發(fā)現(xiàn)這些研究的價值。例如,您曾注意到一些長的方法有時難以理解 嗎?是否曾無法理解嵌套很深的條件從句小的邏輯?您的避開這類代碼的本能 是正確的。一些長的方法和帶有大量路徑的方法渥?難以理解的,有趣的是,這 類方法容易導致缺陷。我將使用一些例子展示我要表達的意思。數(shù)字的海洋研究顯示,平均每人在其大腦中大約能夠處理7 (±2)位數(shù)字。這就是為什么 大多數(shù)人可以很容易地記住電話號碼,但卻很難記住大于7位數(shù)字的信用卡號 碼、發(fā)射次序和其他數(shù)字序列的原因。此原理還可以應用于代碼的理解上。您以前大概已經(jīng)看到過類似清單1中所示 的代碼片段:清單1.適用記憶數(shù)字的原理if (entit
6、ylmplvo != null) list actions = entitytmplvo. getentilies();if (actions = null) actions = new arraylist();iterator enltr 二 actions, iterator();whi 1 e (enttr. hasnext () entityresultvalueobject arvo = (entityresultvalueobject) actionltr.next ();float entityresult = arvo. getactionresultido ;if (asso
7、cpersoneventlist. contains(actionresult) assocpersonflag 二 true;if (arvl. getbyname( appconstants. entity_result_denial_of_service).getid(). equals(entityresult) if (actionbasistd. equal s (actiontmplvo. getactionbasistdo) assocflag = true;if (arvl. getbyname(appconstants. enttty_result_tnvol_servtc
8、e) gctid(). equals(entityresult) if (!reasonld. equals (arv0. getstatusreasonld() assocflag = true;elseentitylmplvo = oldentitylmplvo;清單1展示了 9條不同的路徑。該代碼片段實際上是一個350多行的方法的 一部分,該方法展示了 41條不同的路徑。設想一下,如果您被分配一項任務, 要修改此方法以添加一項新功能。如果您該方法不是您編寫的,您認為您能只做 必要的更改而不會引入任何缺陷嗎?當然,您應該編寫一個測試用例,但您會認為該測試用例能將您的特定更改在條 件從句的海
9、洋中隔離起來嗎?測量路徑復雜度圈層雜友?是在我前面提到的那些研究期間開創(chuàng)的,它可以精確地測量路徑復雜 度。通過利用某一方法路由不同的路徑,這一基于整數(shù)的度量可適當?shù)孛枋龇椒?復雜度。實際上,過去幾年的各種研究已經(jīng)確定:圈復雜度(或cc)大于10的 方法存在很大的岀錯風險。因為cc通過某一方法來表示路徑,這是用來確定某 一方法到達100%的覆蓋率將需要多少測試用例的一個好方法。例如,以下代碼(您可能記得本系列的第一篇文章中使用過它)包含一個邏輯缺陷:清單2. pathcoverage有一個缺陷!public class pathcoverage public string pathexample
10、(boolean condition)string value = null;if(condition) value 二""+ condition + " ;return value. trim();作為響應,我可以編寫一個測試,它將達到100%的行覆蓋率:清單3. 一個測試產生完全覆蓋!import junit. framework. tcstceisc;public class pathcoveragetest extends testcase public final void testpathexample() pathcoverage clzzunder
11、tst 二 new pathcoverage();string value = clzzundertst. p3thexeimple(true); assertequals (''should be truez truez value);接下來,我將運行一個代碼覆蓋率工具,比如cobertura,并將獲得如圖1中 所示的報告: 圖 l cobertura 報告10 1if(condition)11 1value = h " + condition +12 j13 1return value匸rimf);14 15 file edit view go bookmarks
12、 tools helpcoverage report - com. van ward.co verage.example2.pathcoverageclasses in this fileline coveragebranch coveragecomplexitypathcoveraqe1dd%1 2reports generated by cobertura,done哦,有點失望。代碼覆蓋率報告指示100%的覆蓋率,但我們知道這是一個謀導。二對二注意,清單2屮的?pathexample()?方法有一個值為2的cc (一個用于默認路 徑,一個用于?if?路徑)。使用cc作為更精確的覆蓋率測量尺
13、度意味著第二個 測試用例是必需的。在這里,它將是不進入?if?條件語句而采用的路徑,如清單 4 屮的?testpathexamplefalse () ?方法所示:清單4.沿著較少采用的路徑向下import junit. framework. testcase;public class pathcoveragetest extends testcase public final void testpathexample() pathcoverage clzzundertst 二 new pathcoverage();string value 二 clzzundertst. pathexample
14、(true); dssertequals("should be tvalue);public final void testpathexamplefalse() pathcoverage clzzundertst 二 new pathcoverage ();string value 二 clzzundertst. pathexample(false);assertequals("should be false", "false", value);正如您可以看到的,運行這個新測試用例會產生一個令人討厭的?nullpointerexception0
15、在這里,有趣的是我們可以使用圈復雜度岡是? 使用代碼覆蓋率來找出這個缺陷。代碼覆蓋率指示我們己經(jīng)在一個測試用例之后 完成了此操作,但cc卻會強迫我們編寫額外的測試用例。不算太壞,是吧?幸運的是,這里的測試屮的方法冇一個值為2的cco設想一下該缺陷被隱藏在 cc為102的方法中的情況。祝您好運找到它!圖表上的ccjava開發(fā)人員可使用一些開放源碼工具來報告圈復朵度。其小一個這樣的工具 是javancss,它通過檢查java源文件來確定方法和類的長度。此外,此t具 還收集代碼庫中每個方法的圈復雜度。通過利用ant任務或maven插件配置 javancss,可以生成一個列出以下內容的xml報告:每個
16、包中的類、方法、非注釋代碼行和各種注釋樣式的總數(shù)。每個類中非注釋代碼行、方法、內部類和javadoc注釋的總數(shù)。代碼庫小每個方法的非注釋代碼行的總數(shù)和圈復雜度。該工具附帶了少量樣式表,可以使用它們來生成總結數(shù)據(jù)的html報告。例如, 圖2闡述了 maven生成的報告:圖2. maven生成的javancss報告此報告中帶冇?7b刀30 functions containing the most akss?標簽的部分詳細 描述了代碼庫中最長的方法,順便提一句,該方法幾乎總欝與包含最大圈復雜度的方法相關聯(lián)。例如,該報告列出了?dblnsertqueue?類的?updatepcensus()? 方法
17、,因為此方法的非注釋行總數(shù)為283,圈復雜度(標記為ccn)為114。正如上面所演示的,圈復雜度是代碼復雜度的一個好的指示器;此外,它還是用 于開發(fā)人員測試的一個極好的衡量器。一個好的經(jīng)驗法則是創(chuàng)建數(shù)量與將被測試 代碼的圈復雜度值相等的測試用例。在圖2屮所見的?updatcpccnsuso?方法 屮,將需要114個測試用例來達到完全覆蓋。分而治之在面對指示高圈復雜度值的報告吋,第一個行動是檢驗所有相應測試的存在。如 果存在一些測試,測試的數(shù)量是多少?除了極少數(shù)代碼庫以外,幾乎所冇代碼庫 實際上都有114個測試用例用于?updatcpccnsus()?方法(實際上,為一個方法 編寫如此多的測試用
18、例可能會花費很長時間)。但即使是很小的一點進步,它也 是減少方法中存在缺陷風險的一個偉大開始。如果沒有任何相關的測試用例,顯然需耍測試該方法。您首先想到的可能是:到 重構的時間了,但這樣做將打破第一個重構規(guī)則,即將編寫一個測試用例。先編 寫測試用例會降低重構小的風險。減少圈復雜度的最有效方式是隔離代碼部分, 將它們放入新的方法屮。這會降低復雜度,使方法更容易管理(因此更容易測試)。 當然,隨后應該測試那些更小的方法。在持續(xù)集成環(huán)境屮,夠7辦刃變化?評估方法的復雜度是有可能的。如果是第一次 運行報告,那么您可以監(jiān)視方法的復雜度值或任何相關的成長度(growth)。如 果在cc中看到一個成長度,那
19、么您可以采取適當?shù)膭幼鳌H绻骋环椒ǖ腸c值在不斷增長,那么您冇兩個響應選擇:確保相關測試的健康情況仍然表現(xiàn)為減少風險。評估重構方法減少任何長期維護問題的對能性。還要注意的是,javancss不是惟一用于java平臺促進復雜度報告的工具。pmd 是另一個分析jewel源文件的開源項目,它有一系列的規(guī)則,其中z就是報告 圈復雜度。checkstyle是另一個具冇類似的圈復雜度規(guī)則的開放源碼項目。p1d 和checkstyle都有ant任務和maven插件(請參閱?參考資料,從那里獲得 關于至此為止討論的所有工具的更多信息。)使用復雜度度量因為圈復雜度是如此好的一個代碼復雜度指示器,所以測試驅動的開發(fā) (test-driven development)和低cc值z間存在著緊密和關的聯(lián)系。在編寫測 試時(注意,我沒有暗示是第一茨),開發(fā)人員通常傾向于編寫不太復朵的代碼, 氏、人復雜的代碼難以測試。如果您發(fā)現(xiàn)自己難以編寫某一代碼,那么這是一種警 示,表示正在測試的代碼可能很復雜。在這些情況下,tdd的簡短的“代碼、 測試、代碼、測試”循環(huán)將導致重構,而這將繼續(xù)
溫馨提示
- 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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 合同zao的法律認定
- 合同法第115條內容
- 統(tǒng)考版2025屆高考歷史一輪復習課后限時集訓39新文化運動與馬克思主義的傳播含解析新人教版
- 2024年山東客運從業(yè)資格證應用能力考試
- 2024最高額質押反擔保合同
- 2024購房合同能否更名以及如何更名
- 專題10.人物描寫及其作用-2023年三升四語文暑期閱讀專項提升(統(tǒng)編版)
- 四年級讀書卡完整版
- 三年級語文上冊第五單元測試卷-基礎知識與綜合能力篇 含答案 部編版
- 2024成品柴油買賣合同
- 2024年地下水監(jiān)測打井施工合同
- 2023年江門市基層公共就業(yè)創(chuàng)業(yè)服務崗位招聘考試真題
- 圖解《黑神話悟空》微課件
- 期中模擬測試卷3(試題)-2024-2025學年三年級上冊數(shù)學(福建)
- 電子產品回收處理協(xié)議
- 礦石交易居間合同模板
- 期中測試卷(試題)-2024-2025學年人教版數(shù)學四年級上冊
- LNG(天然氣)供氣站(氣化站)安全應急救援預案
- 信息技術咨詢服務合同5篇
- 衛(wèi)生紙購銷合同書
- 16G362鋼筋混凝土結構預埋件(詳細書簽)圖集
評論
0/150
提交評論