提供代码质量之静态代码检查

tani8713 3年前
   <h2>前言</h2>    <p>在团队Android项目开发过程中,难免会出现一些比较不容易发现,但是又比较低级的bug。而且因为每个开发人员的编码习惯不同,写出的代码也会有差异。为了保证团队开发中代码的规范以及尽量避免低级bug,我们往往需要一些工具来进行严格的检查。下面将介绍在项目中用到的四种插件 <strong>lint</strong> 、 <strong>findBugs</strong> 、 <strong>PMD</strong> 、 <strong>CheckStyles</strong> 的功能和使用方式,以及如何将多个插件整合在一起,在方便使用的同时尽量做到与项目工程解耦。</p>    <h2>一、lint</h2>    <p>Lint是Android Studio提供的一个代码检测工具,通过它开发者不用运行或者写测试代码,就可以发现和纠正问题,优化代码结构。每个被检测到的问题,都会生成一条描述信息并指明相应的严重性级别,当然这个严重性级别我们也可以自己设置的。</p>    <h3>检测范围</h3>    <ul>     <li>潜在的bug</li>     <li>可优化的代码</li>     <li>安全性</li>     <li>性能</li>     <li>可用性</li>     <li>可访问性</li>     <li> <p>国际化</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/d02587490859b99e3d050406c9a6354a.png"></p> </li>    </ul>    <h3>插件安装</h3>    <p>Android Studio自带,无需安装。</p>    <h3>插件使用</h3>    <p>通过Gradle运行lint</p>    <p>在工程的根目录下运行相应的gradle task。</p>    <ul>     <li>Windows</li>    </ul>    <pre>  <code class="language-java">gradle lint</code></pre>    <ul>     <li>Linux 或者 MAC</li>    </ul>    <pre>  <code class="language-java">./gradlew lint</code></pre>    <p>当运行上面的命令执行完后,就会在项目目录/app/build/outputs/lint-results-debug.html生成相应的文件,可用浏览器打开查看。</p>    <p>手动运行lint</p>    <p>有时我们可能只针对某个文件或者某个目录进行检测,这时使用gradle的方式就比较麻烦了,所以Android Studio提供给我们手动运行lint的方式。</p>    <ul>     <li>在AS的工程下选择module、目录或者文件</li>     <li>右键选择 <strong>Analyze > Inspect Code.</strong></li>     <li> <p>此时会出现一个选择“指定检测范围”的dialog</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/aca8246c0d07d384f91347251b4d9b96.png"></p> </li>     <li> <p>配置完成后,点击 <strong>OK</strong> 按钮,进行检测。检测结果如下图所示,左边是检测类型的树形结构,右边则展示详细的信息。</p> <p><img src="https://simg.open-open.com/show/b94455a4335a3ca4bd468e69430bc664.png"></p> </li>    </ul>    <p>注:详细的使用,请看官网文档 <a href="/misc/goto?guid=4959733503687351821" rel="nofollow,noindex">Improve Your Code with Lint</a></p>    <h2>二、findBugs</h2>    <p>FindBugs是一个Java静态分析工具,用来检查类或者jar文件,用来发现可能的问题。检测完成之后会生成一份详细的报告,借助这份报告可以找到潜在的bug,比如NullPointException,特定的资源没有关闭,查询数据库没有调用Cursor.close()等</p>    <h3>检测范围</h3>    <ul>     <li>常见代码错误,序列化错误</li>     <li>可能导致错误的代码,如空指针引用</li>     <li>国际化相关问题:如错误的字符串转换</li>     <li>可能受到的恶意攻击,如访问权限修饰符的定义等</li>     <li>多线程的正确性:如多线程编程时常见的同步,线程调度问题。</li>     <li>运行时性能问题:如由变量定义,方法调用导致的代码低效问题</li>    </ul>    <h3>插件安装</h3>    <p>在Android Studio中选择 <strong>Preferences -> Plugins</strong> ,输入查找findBugs进行插件安装。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/b6007dcce096005bc7e349245e72be0f.jpg"></p>    <h3>插件使用</h3>    <p>在build.gradle文件中,按照下面步骤进行设置:</p>    <ol>     <li>添加plugin apply plugin:'findbugs'</li>     <li>定义任务,指定输出格式</li>    </ol>    <pre>  <code class="language-java">task findbugs(type: FindBugs, dependsOn: "assembleDebug") {      ignoreFailures = true      effort = "max"      reportLevel = "high"      excludeFilter = new File("$configDir/findbugs/findbugs-filter.xml")      classes = files("${project.rootDir}/app/build/intermediates/classes")        source 'src'      include '**/*.java'      exclude '**/gen/**'        reports {          xml.enabled = false          html.enabled = true          xml {              destination "$reportsDir/findbugs/findbugs.xml"          }          html {              destination "$reportsDir/findbugs/findbugs.html"          }      }        classpath = files()  }</code></pre>    <p>这里要注意因为findBugs是检查class文件,所以在定义task的时候,我们是 <strong>dependsOn: "assembleDebug"</strong> ,确保运行findbugs的task能够成功检测。</p>    <p>通过 <strong>gradle findbugs</strong> 方式,在工程目录下运行命令,检测完成后,会在制定的目录下生成报告文档。文档支持xml和html两种格式,本文设置的是html格式,可以直接用浏览器打开。</p>    <p>当然,和lint一样,findBugs也支持手动检测的方式。在工程里,右键 <strong>FindBugs -> (选择检测的范围)</strong> 。检测完之后,底部工具栏会跳到 <strong>FindBugs-IEDA</strong> 下,如图所示。</p>    <p><img src="https://simg.open-open.com/show/6c6493095ed87fb3405d9f469db63e06.jpg"></p>    <h2>三、PMD</h2>    <p>PMD是一个很有用的工具,它跟Findbugs类似,但是它不是检测字节码,它是直接检测源代码。它使用静态分析来发现错误。为什么要将它们同时使用呢?因为它们的检测方法不同,可以取到互补的作用。</p>    <h3>检测范围</h3>    <ul>     <li>可能的bug——空的try/catch/finally/switch块。</li>     <li>无用代码(Dead code):无用的本地变量,方法参数和私有方法。</li>     <li>空的if/while语句。</li>     <li>过度复杂的表达式——不必要的if语句,本来可以用while循环但是却用了for循环。</li>     <li>可优化的代码:浪费性能的String/StringBuffer的使用。</li>    </ul>    <h3>插件安装</h3>    <p>同样可以通过AS的plugin进行安装,推荐安装QAPlug-PMD。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/6d4ebdb213e256b52bd9d9aec7038914.jpg"></p>    <h3>插件使用</h3>    <p>在build.gradle文件中进行如下配置</p>    <ul>     <li>导入Plugin: apply plugin: 'pmd'</li>     <li>Task配置</li>    </ul>    <pre>  <code class="language-java">task pmd(type: Pmd) {      ignoreFailures = false      ruleSetFiles = files("$configDir/pmd/pmd-ruleset.xml")      ruleSets = []        source 'src'      include '**/*.java'      exclude '**/gen/**'      exclude 'androidTest/**'      exclude 'test/**'        reports {          xml.enabled = false          html.enabled = true          xml {              destination "$reportsDir/pmd/pmd.xml"          }          html {              destination "$reportsDir/pmd/pmd.html"          }      }  }</code></pre>    <h2>四、CheckStyles</h2>    <p>这个工具用来自动检测java源码。启动之后,可以按照制定的规则对java源码进行检查,被将所有的不符合规范的地方生成报告通知给你。</p>    <h3>检测范围</h3>    <ul>     <li>注解</li>     <li>javadoc注释</li>     <li>命名规范</li>     <li>文件头</li>     <li>导入包规范</li>     <li>尺寸设置</li>     <li>空格</li>     <li>正则表达式</li>     <li>修饰符</li>     <li>代码块</li>     <li>编码问题</li>     <li>类设计问题</li>     <li>重复、度量以及一些杂项</li>    </ul>    <p>总而言之,是一些代码规范问题!!</p>    <h3>插件安装</h3>    <p>通过AS的Plugin进行安装</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/e9d5f4d8ed3ac28cff7203f3bb4e126a.jpg"></p>    <h3>插件使用</h3>    <ul>     <li>导入Plugin</li>    </ul>    <pre>  <code class="language-java">apply plugin: 'checkstyle'</code></pre>    <ul>     <li>设置CheckStyle的版本</li>    </ul>    <pre>  <code class="language-java">checkstyle {      toolVersion '6.1.1'      showViolations true  }</code></pre>    <ul>     <li>配置任务</li>    </ul>    <pre>  <code class="language-java">task checkstyle(type: Checkstyle) {      configFile file("$configDir/checkstyle/k12_checkstyle.xml")      configProperties.checkstyleSuppressionsPath = file("$configDir/checkstyle/suppressions.xml").absolutePath      source 'src'      include '**/*.java'      exclude '**/gen/**'      exclude 'androidTest/**'      exclude 'test/**'      ignoreFailures true      classpath = files()  }</code></pre>    <h2>五、插件的接入与使用</h2>    <h3>检测范围</h3>    <p>lint、PMD、findBugs和CheckStyle检测范围之和。</p>    <h3>插件安装</h3>    <ul>     <li>下载整合插件的文件包,和app工程目录同级放置。</li>     <li>在app的build.gradle文件导入整合插件脚本</li>    </ul>    <pre>  <code class="language-java">apply from: '../config/quality.gradle'</code></pre>    <h3>插件使用</h3>    <ul>     <li>修改 <strong>quality.gradle</strong> 的appDir字段,设置检测的工程目录</li>    </ul>    <pre>  <code class="language-java">// 应用目录名称  def appDir = "app-k12"</code></pre>    <ul>     <li>进入工程根目录,运行 <strong>gradle check</strong> ,检测完成后,会在 <strong>build/reports</strong> 下生成相应的检测报告文件。当然也可以按照每个插件的使用方式单独使用。</li>    </ul>    <p> </p>    <p> </p>    <p>来自:http://www.jianshu.com/p/2b8d34b2267c</p>    <p> </p>