閱讀275 返回首頁    go 阿裏雲 go 技術社區[雲棲]


提高代碼質量-工具篇

注:這是一片翻譯文章:原文:How to improve quality and syntax of your Android code,為了理解連貫,翻譯過程中我修改了一些陳述邏輯和順序,同時也加了一些自己的補充。

在這片文章中,我將從工具使用的角度上講述如何提高 Android 代碼質量,這些自動化工具包括 Checksytle、Findbugs、PMD 和 Android Lint. 團隊中代碼意識不一致,水平參差不齊,代碼風格迥異,定下的規範也是熟視無睹。這時候就需要借助工具的力量,利用工具自動地幫助我們檢測代碼,避免代碼惡習,預防蟻穴壞堤。

0.1 Fork 這個例子工程

我強烈建議你fork這個例子工程,所有的使用事列都會在這個demo中呈現,同時你可以測試你自己寫的規則。

0.2 關於 Gradle 的 Task

理解 Gradle 的 Task 是理解這篇文章的基礎,我強烈建議你多看看關於Gradle Task的文章(例如這篇還有這篇),當然,本文也是滿滿的例子,所以你很容易理解,這也是我建議你 fork 我的代碼倉庫的原因,把工程導入你的 Android studio,然後你將看到熟悉的 Gradle Task 腳本。如果你還是不太理解,也不用擔心,我將最大努力的寫好注釋。

0.3 關於 這個 demo 的層級結構

Gradle 腳本可以分散在不同的文件中,我在工程中寫了三個 gradle 文件:

1 Checkstyle

Check style 是一個幫助開發者維持編碼規範標準的一個工具,它能自動地檢測 Java 代碼,以減少人工檢測代碼的成本。當你啟用 Checkstyle,它能解析你的代碼並能告訴你代碼中的錯誤或者不符合定義的規範的地方。

1.1 Android Studio 插件

Checkstyle 提供了多種IDE的插件支持,Android Studio 也不例外。
進入Android Studio設置頁麵,在插件欄輸入Checkstyle:

Checkstyle插件

如果你還沒安裝 Checkstyle 的插件,進入下載頁下載,然後重啟 Android Studio。啟動 Android studio 後進入 Checkstyle 的設置頁麵:

Checkstyle設置

在這裏我們可以設置 Checkstyle 插件掃描範圍,配置文件等信息,默認使用的配置文件是官方提供的文件:sun_checks.xml,我們也可以根據自己項目的需要定義自己的配置文件,配置規則可以參考官方文檔
設置完成之後點擊 “Apply” 或者 “ok” 按鈕,回到代碼中,我們便可以看到 Checkstyle 給我們的提示:

Checksylte高亮提示

1.2 Gradle 方式使用Checkstyle

如果我們需要把 Checkstyle 繼承到自動編譯服務器中,例如:jenkins,我們需要利用 Gradle Task來執行 Checkstyle,下麵這段腳本展示了在 Gradle task 的 Checkstyle 的基本配置:

task checkstyle(type: Checkstyle) {
    configFile file("${project.rootDir}/config/quality/checkstyle/checkstyle.xml") // Where my    checkstyle config is...
    configProperties.checkstyleSuppressionsPath = file("${project.rootDir}/config/quality/checkstyle/suppressions.xml").absolutePath // Where is my suppressions file for checkstyle is...
    source 'src'
    include '**/*.java'
    exclude '**/gen/**'
    classpath = files()
}

這個 task 將會根據你指定的 checkstyle.xml 和 suppressions.xml 文件來分析你的代碼。你可以在 Android Studio 中執行這個任務:

執行完成之後,checkstyle 工具將會把每一個不合法的問題顯示在控製台中。

2 FindBugs

FindBugs 這個名字本身已經揭示了它的作用,“FindBugs uses static analysis to inspect Java bytecode for occurrences of bug patterns.” FindBugs 是一個工具,它能通過靜態分析方式掃描 Java 字節碼,發現其中的可能出現 bug 的代碼,它能發現一些常規的低級的錯誤,例如一些錯誤的邏輯操作,也能發現一些比較隱晦的錯誤。
例如:

   Person person = (Person) map.get("bob");
    if (person != null) {
        person.updateAccessTime();
    }
    String name = person.getName();

最後一行代碼,可能會出現空指針錯誤。
又如:

    b.replace('b', 'p');
    if(b.equals("pop")) {
        Log.d("","");
    }

b.replace('b', ‘p’);這段代碼對b不會產生影響,所以是無效的。

2.1 Android Studio 插件

同樣,FIndbugs 也提供了 Android Studio 的插件支持,插件的獲取過程和 Checkstyle 一樣,在安裝後之後重啟 Android studio。值得注意的是 Findbugs 分析的是 Java 字節碼,所以在啟用 Findbugs 之前要保證你的工程是編譯過的,在 FIndbugs 掃描之後,如果發現問題,會在對應的代碼出給出提示:

findbugs提示

2.2 Gradle 腳本使用

在Gradle使用非常簡單,下麵的腳本展示了如何 FindBugs:

task findbugs(type: FindBugs) {
    ignoreFailures = false
    effort = "max"
    reportLevel = "high"
    excludeFilter = new File("${project.rootDir}/config/quality/findbugs/findbugs-filter.xml")
    classes = files("${project.rootDir}/app/build/classes")
    source 'src'
    include '**/*.java'
   exclude '**/gen/**'

    reports {
       xml.enabled = false
        html.enabled = true
        xml {
       destination "$project.buildDir/reports/findbugs/findbugs.xml"
   }
    html {
        destination "$project.buildDir/reports/findbugs/findbugs.html"
    }
}

    classpath = files()
}

腳本任務和 Checkstyle 類似,FindBugs 可以根據我們指定的範圍進行掃描,這個範圍我們可以通過一個過濾規則文件來製定掃描結果報告支持 HTML 和 XML 兩種格式。excludeFilter 指定了過濾器配置文件,reports 指定了檢測報告的文件格式和文件地址。執行 Findbugs 的 task 非常簡單,和 Checkstyle 一樣。

2.3 Findbugs 使用技巧

我強烈建議為 Findbugs 配置一個過濾文件,因為 Android 工程和 Java 工程稍微有些不一樣,Android 工程自動生成的 R 文件並不符合 Findbugs 的規範,需要過濾掉。另外要注意的是:Findbugs 分析的是字節碼,你需要先編譯,再進行 Findbugs 的分析。

3 PMD

這個工具比較有趣:其實 PMD 真正的名字並不是 PMD 。 在其官方網站上你會發現兩個非常有趣的名字:

  • Pretty Much Done
  • Project Meets Deadline

事實上 PMD 是一個非常強大的工具,它的作用類似 Findbugs,但是它的檢測掃描是基於源碼的,而且 PMD 不僅僅能檢測 Java 語言,還能檢測其他語言。PMD 的目標和 Findbugsd 非常的相似,都是通過定義的規則靜態分析代碼中可能出現的錯誤,為什麼要同時使用 PMD 和 Findbugs呢?由於 Findbugs 和 PMD 的掃描方式不一樣,PMD 能發現的一些 Findbugs 發現不了的問題,反之亦然。

3.1 Android 插件中使用

插件的下載過程不再贅述,安裝完成重啟之後,到頂部菜單 Tools 欄目可以找到 QAplug 選項,可以執行代碼分析:

PMD代碼分析

執行完成,會在控製台輸出結果:

PMD執行結果

3.2 在 Gradle 腳本中使用

下麵的腳本代碼展示了如何使用PMD:

task pmd(type: Pmd) {
    ruleSetFiles = files("${project.rootDir}/config/quality/pmd/pmd-ruleset.xml")
    ignoreFailures = false
    ruleSets = []

   source 'src'
   include '**/*.java'
   exclude '**/gen/**'

    reports {
        xml.enabled = false
        html.enabled = true
    xml {
        destination "$project.buildDir/reports/pmd/pmd.xml"
    }
   html {
        destination "$project.buildDir/reports/pmd/pmd.html"
       }
    }
}

配置都和 Findbus 如出一轍,PMD 同樣也可以輸出 HTML 和 XML 報告,例子中選中的是 HTML 格式。我強烈建議你定義自己的 rulesets 文件(規則集合),關於 rulesets的配置,可以參考官方文檔,PMD存在爭議的規則比 Findbugs 要多,例如對於嵌套的 “if statement” 它總是提醒你 “These nested if statements could be combined”,或者對空的 “if statement ” 總是提醒你 “Avoid empty if statements”,不過,我覺得是否需要把嵌套 “if statement” 合並到一個 “if statement” 取決於你或者你的團隊自己來定義,我不太建議合並 “if statement ” 這樣會降低代碼可讀性。執行 PMD 的 task 非常簡單,和 Checkstyle 一樣。

4 Android Lint

“The Android lint tool is a static code analysis tool that checks your Android project source files for potential bugs and optimization improvements for correctness, security, performance, usability, accessibility, and internationalization.” 正如官網所說,Android Lint 是另一個靜態代碼分析工具,專門針對 Android 工程。Android Lint 除了對代碼掃描,分析潛在問題之外,還能對Android的資源進行檢測,無用的資源,錯位的dip資源等。

4.1 Gradle 腳本使用

android {
    lintOptions {
    abortOnError true
     lintConfig file("${project.rootDir}/config/quality/lint/lint.xml")
    // if true, generate an HTML report (with issue explanations, sourcecode, etc)
    htmlReport true
    // optional path to report (default will be lint-results.html in the builddir)
    htmlOutput file("$project.buildDir/reports/lint/lint.html")
}

我建議你單獨指定一個配置文件來決定是否過濾一些規則,規則的定義可以參考最新ADT給出的規則,參考這裏。使用 “severity” 配置為 “ignore” 來過濾指定的規則。 執行 Lint 和執行 Checkstyle 的 task 一樣。執行完成之後到結果輸出目錄中查看報告,例如下麵是我(譯者)執行自己的工程輸出的部分截圖:

5 在一個任務統一使用以上工具

以上介紹完了四個工具,現在我們來看看如何一次同時運行四個工具?我們可以管理 gradle task 之間的依賴關係,使得我們在執行一個 task 任務的同時其他 task 也能被執行。使用 Gradle 提供的方法,我們可以把四個工具的執行任務添加為 “check” task 的依賴:

check.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint'

現在,隻要我們隻想 “check” 這個 task ,Checkstyle、Windbags、PMD 和 Android Lint 都會自動執行。在 commit/push/merge request 之前 執行一下 check 任務,對我們代碼質量的提高將是一種非常棒的方式。執行這個任務比較簡單,你可以在命令行中執行:

    gradlew check

6 總結

正如上文所說,在 Gradle 中使用這些工具是非常簡單的。這些工具不僅能在本地使用,還能部署到我們的自動化編譯服務器上,比如 Jenkins/Hudson,自動處理掃描我們的代碼並輸出報告。

最後更新:2017-06-05 11:32:53

  上一篇:go  Httpclient核心架構設計
  下一篇:go  業務SQL那些事--慎用LIMIT