提高代码质量

来源:互联网 发布:windows部署添加驱动 编辑:程序博客网 时间:2024/05/19 08:43

在这片文章中,我将从工具使用的角度上讲述如何提高Android代码质量,这些自动化工具包括Checksytle,Findbugs,PMD和Android Lint。团队中代码意识不一致,水平参差不齐,代码风格迥异,定下的规范也是熟视无睹。这时候就需要借助工具的力量,利用工具自动地帮助我们检测代码,避免代码恶习,预防蚁穴坏堤。

0.1 Fork这个例子工程

我强烈建议你叉这个例子工程,所有的使用事列都会在这个演示中呈现,同时你可以测试你自己写的规则

0.2关于Gradle的任务

理解Gradle的Task是理解这篇文章的基础,我强烈建议你多看看关于Gradle Task的文章(例如这篇还有这篇),当然,本文也是满满的例子,所以你很容易理解,这如果你还是不太理解,也不用担心,我将最大努力的写好注释。

0.3关于这个demo的层级结构

Gradle脚本可以分散在不同的文件中,我在工程中写了三个gradle文件:

  • 根目录下的gradle文件用来配置工程相关的信息,例如仓库依赖,编译工具版本之类的。
  • app目录下的gradle文件,用来校验Java类。
  • config目录下的gradle文件用来配置了以上提到的几个工具。

1 Checkstyle

检查样式是一个帮助开发者维持编码规范标准的一个工具,它能够自动地检测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任务来执行Checkstyle,下面这段脚本展示了在Gradle任务的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()}

这个任务将会根据你指定的checkstyle.xml和suppressions.xml文件来分析你的代码。你可以在Android Studio中执行这个任务:


执行完成之后,checkstyle工具将会把每一个不合法的问题显示在控制台中。

2个FindBugs


FindBugs这个名字本身已经揭示了它的作用,“FindBugs使用静态分析来检查Java字节码是否出现bug模式。”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指定了过滤器配置文件,报告指定了检测报告的文件格式和文件地址。执行Findbugs的任务非常简单,和Checkstyle一样。

2.3 Findbugs使用技巧

我强烈建议为Findbugs配置一个过滤文件,因为Android工程和Java工程稍微有些不一样,Android工程自动生成的R文件并不符合Findbugs的规范,需要过滤掉。另外要注意的是:Findbugs分析的是字节码,你需要先编译,再进行Findbugs的分析。

3 PMD


这个工具比较有趣:其实PMD真正的名字并不是PMD。在其官方网站上你会发现两个非常有趣的名字:

  • 相当多做了
  • 项目符合截止日期

事实上PMD是一个非常强大的工具,它的作用类似Findbugs,但它的检测扫描是基于源码的,而且PMD不仅仅能检测Java语言,还能检测其他语言.PMD的目标和Findbugsd非常的相似,都是通过定义的规则静态分析代码中可能出现的错误,为什么要同时使用PMD和FindBugs的呢?由于FindBugs的PMD和的扫描方式不一样,PMD能发现的一些FindBugs的发现不了的问题,反之亦然。

3.1 Android插件中使用

插件的下载过程不再赘述,安装完成重启之后,到顶部菜单工具栏目可以找到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格式。我强烈建议你定义自己的规则集文件(规则集合),关于规则集的配置,可以参考官方文档,PMD存在争议的规则比findbugs要多,例如对嵌套的“if语句”它总是提醒你“这些嵌套的if语句可以合并”,或者对空的“if语句”总是提醒你“避免空if语句” ,不过,我觉得是否需要把嵌套“if statement”合并到一个“if statement”取决于你或者你的团队自己来定义,我不太建议合并“if statement”这样会降低代码可读性。执行PMD的任务非常简单,和Checkstyle一样。

4 Android Lint

“Android lint工具是一个静态代码分析工具,它可以检查您的Android项目源文件是否存在潜在的错误,并针对正确性,安全性,性能,可用性,可访问性和国际化等方面进行优化改进。”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给出的规则,参考这里。使用“严重性”配置为“忽略”来过滤指定的规则。执行Lint和执行Checkstyle的任务一样。执行完成之后到结果输出目录中查看报告,例如下面是我(译者)执行自己的工程输出的部分截图:


5在一个任务统一使用以上工具

以上介绍完了四个工具,现在我们来看看如何一次同时运行四个工具?我们可以管理gradle任务之间的依赖关系,使得我们在执行一个任务任务的同时其他任务也能被执行。的方法,我们可以把四个工具的执行任务添加为“check”task的依赖:

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

现在,只要我们只想“check”这个任务,Checkstyle,Windbags,PMD和Android Lint都会自动执行。在commit / push / merge请求之前执行一下check任务,对我们代码质量的提高将是一种非常棒的方式执行这个任务比较简单,你可以在命令行中执行:

    gradlew check

6总结

正如上文所说,在Gradle中使用这些工具是非常简单的。这些工具不仅能在本地使用,还能部署到我们的自动化编译服务器上,比如Jenkins / Hudson,自动处理扫描我们的代码并输出报告。