日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

让开发自动化持续重构 --使用静态分析工具识别代码味道

發(fā)布時間:2025/3/21 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 让开发自动化持续重构 --使用静态分析工具识别代码味道 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

系列內(nèi)容:

此內(nèi)容是該系列的一部分:讓開發(fā)自動化

在過去的幾年里,我曾看過很多項(xiàng)目的大量源代碼,從精美的設(shè)計(jì)到像是用膠帶綁定到一起的代碼。我寫過新的代碼也維護(hù)過其他開發(fā)人員的源代碼。我喜歡編寫新的代碼,但也喜歡采用一些現(xiàn)有的代碼,以某種方法將其簡化或?qū)⒅貜?fù)的代碼提取到一個公共類中。在我早期的工作生涯中,許多人都認(rèn)為如果不編寫新的代碼就不會有好的效率。幸好,在 20 世紀(jì) 90 年代末,Martin Fowler 編寫了?Refactoring一書(參見?參考資料),它使得在不改變外部行為的前提下改進(jìn)現(xiàn)有代碼成為可能。

我在?本系列中所一直推崇的就是?效率:如何減少耗時過程的冗余度,更快速地執(zhí)行它們。在本文的任務(wù)中,我一樣推崇這個目標(biāo),并且將論述怎樣更?有效地執(zhí)行它們。

關(guān)于本系列

作為開發(fā)人員,我們致力于為用戶自動化流程;但許多開發(fā)人員疏忽了自動化我們自己的開發(fā)流程的機(jī)會。為此,我們編寫了?讓開發(fā)自動化系列文章,專門探討軟件開發(fā)流程自動化的實(shí)踐應(yīng)用,為您介紹?何時以及?如何成功應(yīng)用自動化。

重構(gòu)的一個典型方法是在引入新代碼或更改方法時對現(xiàn)有代碼做出小小的變動。該技巧面臨的挑戰(zhàn)在于一個開發(fā)團(tuán)隊(duì)的開發(fā)人員的應(yīng)用方法不一致,并且很容易錯失重構(gòu)的機(jī)會。這也正是我提倡使用靜態(tài)分析工具識別編碼違規(guī)的原因所在。有了這些工具,您就能夠從總體上了解代碼庫,并且處于類或方法的級別。幸運(yùn)的是,在 Java?程序設(shè)計(jì)中,您可以選擇的可免費(fèi)下載的開源靜態(tài)分析工具很多:CheckStyle、PMD、FindBugs、JavaNCSS、JDepend 等等。

在本文中,您將學(xué)習(xí)如何:

  • 使用 CheckStyle 度量?圈復(fù)雜度(cyclomatic complexity),并提供諸如?Replace Conditional with Polymorphism之類的重構(gòu),以此來減少?條件復(fù)雜度代碼味道
  • 使用 CheckStyle 評估?代碼重復(fù)率,并提供諸如?Pull Up Method之類的重構(gòu),以此來移除?重復(fù)代碼
  • 使用 PMD(或 JavaNCSS)計(jì)算?源代碼行,并提供諸如?Extract Method之類的重構(gòu),以此來淡化?大類代碼味道
  • 使用 CheckStyle(或 JDepend)確定一個類的?傳出耦合度(efferent coupling),并提供諸如?Move Method之類的重構(gòu),以此來除掉?過多的導(dǎo)入代碼味道

我將使用如下的通用格式來檢查每一種代碼味道:

  • 描述可以指示出代碼里面的問題的味道
  • 定義可以找到該味道的度量方法
  • 展示可以度量代碼味道的工具
  • 提供用于修復(fù)代碼味道的重構(gòu)和模式(在某些情況下)
  • 實(shí)質(zhì)上,這個方法提供了一個找到和修復(fù)整個代碼庫中的代碼味道的一個框架。這樣您就可以更好地了解到代碼庫中較危險(xiǎn)的部分,然后再做出更改。更好的是,我還會向您展示如何將這個方法集成到自動構(gòu)建中。

    您的代碼有 么?

    所謂代碼味道其實(shí)只是一種?提示,提示一些內(nèi)容可能存在錯誤。和模式類似,代碼味道提供了一個通用詞匯表,您可以用它來快速識別這些類型的潛在問題。在文章中?真實(shí)地示范代碼味道是很有難度的,因?yàn)樗赡馨ê芏嘈写a,這樣就過分地加大了文章的篇幅。因此,我會只針對其中的一些味道進(jìn)行示范,然后您就可以根據(jù)查看特定代碼味道的經(jīng)驗(yàn)進(jìn)行推斷,識別出剩余的代碼味道。

    條件復(fù)雜度

    味道:條件復(fù)雜度

    度量:圈復(fù)雜度

    工具:CheckStyle、JavaNCSS 以及 PMD

    重構(gòu):Replace Conditional with Polymorphism、Extract Method

    味道

    條件復(fù)雜度可以以幾種不同的方式出現(xiàn)在源代碼中。這種代碼味道的一個例子就是含有多個條件語句,如?if、while或者?for語句。另一種條件復(fù)雜度是以?switch語句的形式呈現(xiàn)出來的,如清單 1 所示:

    清單 1. 使用?switch語句來執(zhí)行條件行為
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 ... switch (beerType) { ?case LAGER:? ???System.out.println("Ingredients are..."); ????... ????break; ?case BROWNALE: ???System.out.println("Ingredients are..."); ????... ????break; ?case PORTER? ???System.out.println("Ingredients are..."); ????... ????break; ?case STOUT: ???System.out.println("Ingredients are..."); ????... ????break; ?case PALELAGER: ???System.out.println("Ingredients are..."); ????... ????break; ?... ?default: ???System.out.println("INVALID."); ????... ????break; } ...

    switch語句本身并沒有不妥。但當(dāng)一個語句包含太多的選擇和代碼時,它就可能暗示有需要重構(gòu)的代碼。

    度量

    要確定條件復(fù)雜度代碼味道,需要確定方法的?圈復(fù)雜度。圈復(fù)雜度是一種度量方法,由 Thomas McCabe 于 1975 年定義。圈復(fù)雜度數(shù)(Cyclomatic Complexity Number,CCN)度量一個方法中某一路徑的數(shù)量。無論一個方法中有多少條路徑,它的起始 CNN 都從 1 開始。每一個條件構(gòu)造,如?if、switch、while和?for語句,都被分配一個 1 值和異常路徑。一個方法的總的 CCN 表明了它的復(fù)雜度。很多人認(rèn)為當(dāng) CCN 為 10 或超過 10 時,就表明該方法過于復(fù)雜。

    工具

    CheckStyle、JavaNCSS、以及 PMD 都是度量圈復(fù)雜度的開源工具。清單 2 展示了用 XML 定義的 CheckStyle 規(guī)則文件的一個代碼片斷。CyclomaticComplexity模塊定義了一個方法的 CCN 的最大限度。

    清單 2. 配置 CheckStyle,查找圈復(fù)雜度為 10 或大于 10 的方法
    1 2 3 <module name="CyclomaticComplexity"> ?<property name="max" value="10"/> </module>

    用清單 2 的 CheckStyle 規(guī)則文件、清單 3 的 Gant 例子來示范如何將 CheckStyle 作為一個自動構(gòu)建的一部分來運(yùn)行。(參見?什么是 Gant ?側(cè)邊欄):

    清單 3. 使用 Gant 腳本來執(zhí)行 CheckStyle 檢查
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 target(findHighCcn:"Finds method with a high cyclomatic complexity number"){ ?Ant.mkdir(dir:"target/reports") ?Ant.taskdef(name:"checkstyle", ???classname:"com.puppycrawl.tools.checkstyle.CheckStyleTask", ???classpathref:"build.classpath") ?Ant.checkstyle(shortFilenames:"true", config:"config/checkstyle/cs_checks.xml", ???failOnViolation:"false", failureProperty:"checks.failed", classpathref:"libdir") { ???formatter(type:"xml", tofile:"target/reports/checkstyle_report.xml") ???formatter(type:"html", tofile:"target/reports/checkstyle_report.html") ???fileset(dir:"src"){ ?????include(name:"**/*.java") ???} ?} }
    什么是 Gant ?

    Gant 是一個自動構(gòu)建工具,它提供了一個支持構(gòu)建依賴關(guān)系的表達(dá)能力強(qiáng)的編程語言。開發(fā)人員利用 Groovy 編程語言的強(qiáng)大功能編寫 Gant 腳本。由于 Gant 提供對 Ant 的 API 的完全訪問,所以任何可以運(yùn)行于 Ant 的東西都可以從 Gant 腳本運(yùn)行。(參見 “用 Gant 構(gòu)建軟件” 教程,了解 Gant。)

    清單 3 中的 Gant 腳本創(chuàng)建了圖 1 中展示的 CheckStyle 報(bào)告。該圖下面的部分指示出了一個方法的 CheckStyle 圈復(fù)雜度違規(guī)。

    圖 1. CheckStyle 報(bào)告根據(jù)過高的 CCN 來指示一種方法失敗

    重構(gòu)

    圖 2 為用 UML 表示的?Replace Conditional with Polymorphism重構(gòu):

    圖 2. 用多態(tài)替代條件語句

    在圖 2 中,我:

  • 創(chuàng)建了一個叫做?BeerType的 Java 界面
  • 定義了一個通用的?showIngredients()方法
  • 為每一個?BeerType創(chuàng)建了一個實(shí)現(xiàn)類
  • 為了使文章保持簡潔,我僅為每一個類提供一個方法的實(shí)現(xiàn)。顯然,創(chuàng)建一個界面的方法可能不只一個。重構(gòu)能夠使代碼更易于維護(hù),如 Replace Conditional with Polymorphism 和 Extract Method(本文稍后將會討論)。

    重復(fù)代碼

    味道:重復(fù)代碼

    度量:代碼重復(fù)率

    工具:CheckStyle、PMD

    重構(gòu):Extract Method、Pull Up Method、Form Template Method、Substitute Algorithm

    味道

    重復(fù)代碼可能在代碼庫中悄然發(fā)生。有時,復(fù)制粘貼某些代碼要比將該行為泛化到另一個類更簡單。但復(fù)制粘貼的方法存在一個問題,即它強(qiáng)制將代碼復(fù)制多份,并且需要維護(hù)。而且當(dāng)復(fù)制出的代碼發(fā)生輕微的變化而引發(fā)行為不一致時,就會發(fā)生更不易察覺的問題,具體取決于哪個方法在執(zhí)行該行為。清單 4 是一個關(guān)閉代碼庫連接的代碼示例,相同的代碼出現(xiàn)在兩種方法中:

    清單 4. 重復(fù)代碼
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public Collection findAllStates(String sql) { ... ?try { ???if (resultSet != null) { ?????resultSet.close(); ???} ???if (stmt != null) { ?????stmt.close(); ???} ???if (conn != null) { ????conn.close(); ??} ??catch (SQLException se) { ????throw new RuntimeException(se); ??} } ... } ... public int create(String sql, Beer beer) { ... ?try { ???if (resultSet != null) { ?????resultSet.close(); ???} ???if (stmt != null) { ?????stmt.close(); ???} ???if (conn != null) { ????conn.close(); ??} ??catch (SQLException se) { ????throw new RuntimeException(se); ??} } ... }
    我有性能更好的 IDE

    雖然在本文的例子中我使用 Gant 來運(yùn)行查找特定味道的工具,但是使用 IDE 也同樣可以解決這些問題。Eclipse IDE 就有很多靜態(tài)分析工具的插件。但我仍然推薦使用自動構(gòu)建工具,因?yàn)檫@樣可以在其他環(huán)境中運(yùn)行集成構(gòu)建,無需使用 IDE。

    度量

    查找重復(fù)代碼的度量方法是在代碼庫中的類的內(nèi)部和其他類之間搜索代碼重復(fù)。沒有工具的話,類間的重復(fù)就更難評估。由于復(fù)制的代碼通常都會發(fā)生一些輕微的變化,因此不僅要度量完全相同的代碼,而且要度量?相似的代碼,兩者都很重要。

    工具

    PMD 的 Copy/Paste Detector(CPD)與 CheckStyle 這兩種開源工具可以用于在整個 Java 代碼庫中查找相似的代碼。清單 5 中的 CheckStyle 配置文件例子示范了如何使用?StrictDuplicateCode模塊:

    清單 5. 使用 CheckStyle 找到至少 10 行重復(fù)代碼
    1 2 3 <module name="StrictDuplicateCode"> ?<property name="min" value="10"/> </module>

    清單 5 中的?min屬性設(shè)置了 CheckStyle 將會標(biāo)記出的最小重復(fù)行數(shù),以供查閱。在這樣的情況下,它將只指示出那些至少有 10 行類似或重復(fù)的代碼塊。

    圖 3 展示了自動構(gòu)建運(yùn)行后,清單 5 中的模塊設(shè)置的結(jié)果:

    圖 3. CheckStyle 報(bào)告指示代碼重復(fù)度過高

    重構(gòu)

    在清單 6 中,我用了?清單 4中的重復(fù)代碼,使用了?Pull Up Method重構(gòu)來降低重復(fù)度 —將行為從較大方法提取到一個抽象類方法中:

    清單 6. Pull Up Method
    1 2 3 4 5 ... } finally { ?closeDbConnection(rs, stmt, conn); } ...
    不要忘記編寫測試程序

    任何時候改變現(xiàn)有代碼,您都需要用諸如 JUnit 這樣的框架編寫相應(yīng)的自動測試程序。修改現(xiàn)有代碼是存在風(fēng)險(xiǎn)的;而將這個風(fēng)險(xiǎn)降到最低的一種方法就是通過測試來驗(yàn)證該行為在現(xiàn)在和將來都有效。

    重復(fù)代碼是難以避免的。我永遠(yuǎn)不會建議一個團(tuán)隊(duì)去努力實(shí)現(xiàn)什么?重復(fù)之類的目標(biāo),這是不切實(shí)際的。然而,確保代碼庫中的重復(fù)代碼不會增多這樣的目標(biāo)是可以實(shí)現(xiàn)的。使用諸如 PMD 的 CPD 或 CheckStyle 這樣的靜態(tài)分析工具,您能夠?qū)⒄麄€分析過程作為自動構(gòu)建的一部分,持續(xù)分析,確定代碼重復(fù)度高的區(qū)域。

    長方法(大類)

    味道:長方法(大類)

    度量:源代碼行數(shù)(SLOC)

    工具:PMD、JavaNCSS、CheckStyle

    重構(gòu): Extract Method、Replace Temp with Query、Introduce Parameter Object、Preserve Whole Object、Replace Method with Method Object

    味道

    我一直在嘗試堅(jiān)持的一條經(jīng)驗(yàn)法則是將方法限制在 20 行或 20 行以內(nèi)。當(dāng)然,這個原則也可能會有例外,但如果我的方法超過 20 行的話,我就會更仔細(xì)地去了解它。通常情況下,長方法和條件復(fù)雜度是息息相關(guān)的。而大類與長方法之間又有著必然的聯(lián)系。我可以給您展示一個 2200 行的方法,這個方法是我在需要維護(hù)的一個項(xiàng)目上發(fā)現(xiàn)的。我將整個含有 25000 行的代碼的類打印了出來,讓我的同事來找出里面的錯誤。這么說吧,當(dāng)我把打印出來的代碼沿著走廊卷起來的時候,他們就已經(jīng)同意我的看法了。

    清單 7 中高亮顯示的部分展示了一個長方法代碼味道示例的一小部分:

    清單 7. 長方法代碼味道
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public void saveLedgerInformation() { ... try { ?if (ledger.getId() != null && filename == null) { ???getLedgerService().saveLedger(ledger); ?} else { ???accessFiles().decompressFiles(files, filenames); ?} ?if (!files.get(0).equals(upload)) { ???upload = files.get(0); ???filename = filenames.get(0); ?} ?if (invalidFiles.isUnsupported(filename)) { ???setError(fileName, message.getMessage()); ?} else { ?LedgerFile entryFile = accessFiles().add(upload, filename); ?if (fileType != null && FileType.valueOf(fileType) != null) { ???entryFile.setFileType(FileType.valueOf(fileType)); ?} ?getFileManagementService().saveLedger(ledger, entryFile); ?if (!FileStatus.OPENED.equals(entryFile.getFileStatus())) { ???getFileManagementService().importLedgerDetails(ledger); ?} ?if (uncompressedFiles.size() > 1) { ???Helper.saveMessage(getText("ledger.file")); ?} ?? ?if (user.getLastName() != null) { ???SearchInfo searchInfo = ServiceLocator.getSearchInfo(); ???searchInfo.setLedgerInfo(null); ???isValid = false; ???setDefaultValues(); ???resetSearchInfo(); ???if (searchInfoValid && ledger != null) { ?????isValid = true; ???} ?} } catch (InvalidDataFileException e) { ?ResultType result = e.getResultType(); ?for (ValidationMessage message : result.getMessages()) { ???setError(fileName, message.getMessage()); ?} ?ledger.setEntryFile(null); } ...

    度量

    在過去的幾年里,SLOC 度量方法被誤認(rèn)為是高效率的象征。盡管我們都知道,并不一定是行數(shù)越多越好。但說到復(fù)雜度,SLOC 可是一個有用的度量方法。一個方法(或類)的行數(shù)越多,將來維護(hù)其代碼就可能越難。

    工具

    清單 8 中的腳本為長方法(大類)找到了 SLOC 度量方法:

    清單 8. 識別過大的類和方法的 Gant 腳本
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 target(findLongMethods:"runs static code analysis"){ Ant.mkdir(dir:"target/reports") Ant.taskdef(name:"pmd", classname:"net.sourceforge.pmd.ant.PMDTask", ??classpathref:"build.classpath") Ant.pmd(shortFilenames:"true"){ ??codeSizeRules.each{ rfile -> ???ruleset(rfile) ??} ??formatter(type:"xml", tofile:"target/reports/pmd_report.xml") ??formatter(type:"html", tofile:"target/reports/pmd_report.html") ??fileset(dir:"src"){ ????include(name:"**/*.java") ??} ?}? }

    我又使用了 Gant 訪問 Ant API 來執(zhí)行 Ant 任務(wù)。在清單 8 中,我調(diào)用 PMD 靜態(tài)分析工具來搜索代碼庫中的長方法。PMD(連同 JavaNCSS 與 CheckStyle)也可以用于查找長方法、大類以及其他代碼味道。

    重構(gòu)

    清單 9 展示了用?Extract Method重構(gòu)來減少?清單 7中的長方法代碼味道的一個例子。將清單 7 的方法中的行為提取到清單 9 的代碼中以后,我就可以從清單 7 的?saveLedgerInformation()方法中調(diào)用新建的?isUserValid()方法了:

    清單 9. Extract Method 重構(gòu)
    1 2 3 4 5 6 7 8 9 10 11 12 13 private boolean isUserValid(User user) { ?boolean isValid = false; ?if (user.getLastName() != null) { ???SearchInfo searchInfo = ServiceLocator.getSearchInfo(); ???searchInfo.setLedgerInfo(null); ???setDefaultValues(); ???resetSearchInfo(); ???if (searchInfoValid && ledger != null) { ?????isValid = true; ???} ?} ?return isValid; }

    通常,長方法和大類也暗示著存在其他代碼味道,如條件復(fù)雜度和重復(fù)代碼。因此,找到這些長方法和大類也就可以修復(fù)其他的問題了。

    太多導(dǎo)入

    味道:太多導(dǎo)入

    度量:傳出耦合(每個類的扇出(fan-out))

    工具:CheckStyle

    重構(gòu):Move Method、Extract Class

    味道

    太多導(dǎo)入表明一個類過多地依賴于其他的類。您會注意到,由于一個類與很多其他的類耦合得太緊密,修改這個類會導(dǎo)致必須對很多其他的類進(jìn)行修改,這時就說明這個類存在這種代碼味道了。清單 10 中的多個導(dǎo)入就是一個例子:

    清單 10. 一個類中的多個導(dǎo)入
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import com.integratebutton.search.SiteQuery; import com.integratebutton.search.OptionsQuery; import com.integratebutton.search.UserQuery; import com.integratebutton.search.VisitsQuery; import com.integratebutton.search.SiteQuery; import com.integratebutton.search.DateQuery; import com.integratebutton.search.EvaluationQuery; import com.integratebutton.search.RangeQuery import com.integratebutton.search.BuildingQuery; import com.integratebutton.search.IPQuery; import com.integratebutton.search.SiteDTO; import com.integratebutton.search.UrlParams; import com.integratebutton.search.SiteUtil; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; ...

    度量

    找到帶有太多責(zé)任的類的一個方法就是通過?傳出耦合度量方法,亦指?扇出復(fù)雜度。扇出復(fù)雜度給被分析的類所依附的每一個類賦值 1。

    工具

    清單 11 展示了一個用 CheckStyle 設(shè)置最大扇出復(fù)雜度數(shù)的例子:

    清單 11. 使用 CheckStyle 設(shè)置最大扇出復(fù)雜度
    1 2 3 <module name="ClassFanOutComplexity"> ?<property name="max" value="10"/> </module>
    Refactoring to Patterns

    工廠方法模式是應(yīng)用重構(gòu)時可以實(shí)現(xiàn)的多種設(shè)計(jì)模式之一。用工廠方法創(chuàng)建類無需顯式定義正在創(chuàng)建的實(shí)際的類。這個模式可以使界面比實(shí)現(xiàn)類更簡單。當(dāng)根據(jù)代碼味道實(shí)現(xiàn)重構(gòu)時,您也可以使用其他的設(shè)計(jì)模式;參見?參考資料查看專門研究這個概念的書籍的鏈接。

    重構(gòu)

    修復(fù)由于太多導(dǎo)入而引發(fā)的耦合過緊的方法有很多種。對于諸如?清單 10中那樣的代碼來說,可用的重構(gòu)就包括?Move Method重構(gòu):將方法從單獨(dú)的 *Query類移動到 Java 界面,并定義所有?Query類必須實(shí)現(xiàn)的通用方法。然后再使用?工廠方法模式,這樣耦合度就與界面相關(guān)聯(lián)了。

    通過使用 Gant 自動構(gòu)建腳本執(zhí)行 CheckStyle Ant 任務(wù),我可以搜索代碼庫,查找過多依賴于其他類的類。當(dāng)修改這些類中的代碼時,就能夠?qū)崿F(xiàn)特定的重構(gòu)(比如 Move Method)和特定的設(shè)計(jì)模式,以逐步改進(jìn)可維護(hù)性。

    重構(gòu)……要盡早且要經(jīng)常進(jìn)行

    持續(xù)集成(Continuous Integration,CI)就是經(jīng)常集成變更。正如其典型的實(shí)現(xiàn)方式一樣,每當(dāng)對項(xiàng)目的版本控制儲存庫做出一個更改時,運(yùn)行于獨(dú)立機(jī)器上的自動 CI 服務(wù)器就會觸發(fā)一個自動構(gòu)建。為了確保?清單 3和?清單 8中的腳本可以在對數(shù)據(jù)庫做出更改時一致地運(yùn)行,您需要配置一個諸如 Hudsona 這樣的 CI 服務(wù)器(參見?參考資料)。Hudson 是以 WAR 文件的形式發(fā)布的,您可以將它放入任何 Java Web 容器中。

    由于?清單 3和?清單 8中的例子使用了 Gant,下面我就簡要介紹一下配置 Hudson CI 服務(wù)器以運(yùn)行 Gant 腳本的步驟:

  • 在 Hudson 的儀表板上為 Hudson 安裝 Gant 插件:首先選擇?Manage Hudson,再選擇?Manage Plugins,然后選擇?Available選項(xiàng)卡。在這個選項(xiàng)卡上選中 Gant 插件復(fù)選框,然后單擊?Install按鈕。
  • 重新啟動 Web 容器(例如,Tomcat)。
  • 選擇?Manage Hudson,然后選擇?Configure System。在?Gant installation部分,鍵入一個惟一的名稱以及 Groovy 安裝到運(yùn)行 Hudson 的機(jī)器上的位置。保存所作更改。
  • 返回到儀表板(選擇?Hudson鏈接),選擇一個?existing Hudson Job,再選擇?Configure,然后單擊?Add build step按鈕,選擇?Invoke Gant script選項(xiàng)。
  • 配置 Hudson,使其運(yùn)行使用 Gant 編寫的自動構(gòu)建腳本。一旦諸如長方法和條件復(fù)雜度這樣的代碼味道被引入到代碼庫中,您立刻就會得到與它們相關(guān)的度量方法的反饋。

    其他味道與重構(gòu)

    并非所有的味道都有相關(guān)的度量方法。但是,靜態(tài)分析工具能夠揭露的味道不止我所示范的這些。表 1 列舉了其他的代碼味道、工具、以及可能的重構(gòu)例子:

    表 1. 其他味道與重構(gòu)
    味道 工具 重構(gòu)

    本文提供了一種使代碼味道與一種度量方法相關(guān)的模式,這種度量方法可以配置為通過自動靜態(tài)分析工具標(biāo)記。您可以使用或不使用特定的設(shè)計(jì)模式來進(jìn)行重構(gòu)。這為您提供了一個以可重復(fù)的方式一致地查找和修復(fù)代碼味道的框架。我堅(jiān)信本文的例子也有助于您使用靜態(tài)分析工具來查找本文未涉及到代碼味道。

    相關(guān)主題

    • 您可以參閱本文在 developerWorks 全球網(wǎng)站上的?英文原文。
    • 讓開發(fā)自動化(Paul Duvall,developerWorks):閱讀整個系列的文章。“持續(xù)檢查”(2006 年 8 月)以及 “用 Eclipse 插件提高代碼質(zhì)量”(2007 年 1 月)部分與本文的主題密切相關(guān)。
    • Smells to Refactorings:一個表格,其中列出了特定的代碼味道的推薦重構(gòu)方法。
    • Refactoring:Improving the Design of Existing Code(Martin Fowler,Addison-Wesley Professional,1999 年):關(guān)于改進(jìn)現(xiàn)有代碼庫設(shè)計(jì)的最基本的書籍。
    • Alpha List of Refactorings:Martin Fowler 編寫的重構(gòu)列表。
    • Refactoring to Patterns(Joshua Kereviesky,Addison-Wesley Professional,2004 年):將設(shè)計(jì)模式應(yīng)用于重構(gòu)來改進(jìn)代碼。我是在聽了 Josh 在丹佛的 Agile 2005 上的講話后才有了將一個大的類打印出來的想法的。
    • “追求代碼質(zhì)量:監(jiān)視圈復(fù)雜度”(Andrew Glover,IBM developerWorks,2006 年 3 月):介紹當(dāng)代碼復(fù)雜度太高時該怎么辦。
    • “追求代碼質(zhì)量:用代碼度量進(jìn)行重構(gòu)”(Andrew Glover,IBM developerWorks,2006 年 5 月):用代碼度量和 Extract Method 模式進(jìn)行有目的地重構(gòu)。
    • Continuous Integration: Improving Software Quality and Reducing Risk”(Paul Duvall 等,Addison-Wesley Signature Series,2007 年):第 7 章(持續(xù)檢查)涵蓋了本文中所涉及的很多工具。
    • “(Ant to Gant) automagically”(Andrew Glover,The Disco Blog,2008 年 4 月):基于現(xiàn)有 Ant 腳本生成 Gant 腳本。
    • “Gant with Hudson in 5 steps”(Andrew Glover,The Disco Blog,2008 年 5 月):配置 Hudson 持續(xù)集成服務(wù)器,以運(yùn)行 Gant 構(gòu)建腳本。
    • “追求代碼質(zhì)量:軟件架構(gòu)的代碼質(zhì)量”(Andrew Glover,IBM developerWorks,2006 年 4 月):使用耦合度量支持系統(tǒng)架構(gòu)。
    • Gant:下載 Gant,開始以一種可預(yù)測、可重復(fù)的方式構(gòu)建軟件。
    • CheckStyle:下載 CheckStyle,搜集度量并更好地評估代碼味道。
    • PMD:下載 PMD,搜集度量并更好地評估代碼味道。
    • Hudson:一個免費(fèi)且開源的持續(xù)集成服務(wù)器。
    • developerWorks Java 技術(shù)專區(qū):這里有數(shù)百篇關(guān)于 Java 編程的文章。
    from:?https://www.ibm.com/developerworks/cn/java/j-ap07088/index.html

    總結(jié)

    以上是生活随笔為你收集整理的让开发自动化持续重构 --使用静态分析工具识别代码味道的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。