让开发自动化持续重构 --使用静态分析工具识别代码味道
系列內(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)入代碼味道
我將使用如下的通用格式來檢查每一種代碼味道:
實(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)替代條件語句
點(diǎn)擊查看大圖
在圖 2 中,我:
為了使文章保持簡潔,我僅為每一個類提供一個方法的實(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,使其運(yùn)行使用 Gant 編寫的自動構(gòu)建腳本。一旦諸如長方法和條件復(fù)雜度這樣的代碼味道被引入到代碼庫中,您立刻就會得到與它們相關(guān)的度量方法的反饋。
其他味道與重構(gòu)
并非所有的味道都有相關(guān)的度量方法。但是,靜態(tài)分析工具能夠揭露的味道不止我所示范的這些。表 1 列舉了其他的代碼味道、工具、以及可能的重構(gòu)例子:
表 1. 其他味道與重構(gòu)
| 死代碼 | PMD | Remove Code |
| 臨時字段 | PMD | Inline Temp |
| 不一致 / 拘謹(jǐn)(uncommunicative)的名稱 | CheckStyle、PMD | Rename Method、Rename Field |
| 長參數(shù)列表 | PMD | Replace Parameter with Method、Preserve Whole Object、Introduce Parameter Object |
本文提供了一種使代碼味道與一種度量方法相關(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 編程的文章。
總結(jié)
以上是生活随笔為你收集整理的让开发自动化持续重构 --使用静态分析工具识别代码味道的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第三部分:Idea重构总结
- 下一篇: 31 天重构学习笔记索引