java pmd checkstyle_提高代码质量 CheckStyle FindBugs PMD

article/2025/9/30 22:45:25

注:这是一篇翻译文章,原文:How to improve quality and syntax of your Android code,为了理解连贯,翻译过程中我修改了一些陈述逻辑和顺序,同时也加了一些自己的补充。

e1357a57dbcbae86d21ead8d63a23637.png

在这片文章中,我将从工具使用的角度上讲述如何提高 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 文件:

根目录下的 gradle 文件,用来配置工程相关的信息,例如仓库依赖,编译工具版本之类的。

1 Checkstyle

e765b08be82bc48e4f29630d37c74574.png

Check style 是一个帮助开发者维持编码规范标准的一个工具,它能自动地检测 Java 代码,以减少人工检测代码的成本。当你启用 Checkstyle,它能解析你的代码并能告诉你代码中的错误或者不符合定义的规范的地方。

1.1 Android Studio 插件

Checkstyle 提供了多种IDE的插件支持,Android Studio 也不例外。

进入Android Studio设置页面,在插件栏输入Checkstyle:

ab5def1919e0be3dfe14c33d55d34550.png

Checkstyle插件

如果你还没安装 Checkstyle 的插件,进入下载页下载,然后重启 Android Studio。启动 Android studio 后进入 Checkstyle 的设置页面:

55d4076b142077059da475a7f4e81d3f.png

Checkstyle设置

在这里我们可以设置 Checkstyle 插件扫描范围,配置文件等信息,默认使用的配置文件是官方提供的文件:sun_checks.xml,我们也可以根据自己项目的需要定义自己的配置文件,配置规则可以参考官方文档。

设置完成之后点击 “Apply” 或者 “ok” 按钮,回到代码中,我们便可以看到 Checkstyle 给我们的提示:

0df417cdf5f8ea882f9be4da60941be4.png

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 中执行这个任务:

458c5402ae60c0158d0b09d38404555c.png

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

2 FindBugs

9a76b2144ce9722530f1733f9ec5389a.png

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 扫描之后,如果发现问题,会在对应的代码出给出提示:

1d7ebec7e0c985dc292e6dde5eb1ba6c.png

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

d8b896b7d9f149a7aea88b186bd82cbf.png

这个工具比较有趣:其实 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 选项,可以执行代码分析:

f5252475e113766c0b0a789a3cc4ee33.png

PMD代码分析

执行完成,会在控制台输出结果:

c0cb8005ff4e80565955e2205e039d60.png

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 一样。执行完成之后到结果输出目录中查看报告,例如下面是我(译者)执行自己的工程输出的部分截图:

825060a4deb2642ad90dbd74d262e3e6.png

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,自动处理扫描我们的代码并输出报告。


http://chatgpt.dhexx.cn/article/j9tv0Kbf.shtml

相关文章

【C语言】 C语言图形编程 俄罗斯方块 课程设计

程序简介 由纯C语言实现的俄罗斯方块小程序,代码长度700行,使用Turbo C图形库美化了界面,并具俄罗斯方块游戏的所有基本功能。玩家可以通过键盘的“上下左右”键移动“方块”,“空格”去翻转方块,每当方块可以将一行“…

简单c语言图形程序设计,c语言实现一些简单图形的打印

1 #define _CRT_SECURE_NO_WARNINGS 1 因为笔者采用的是VS的编译环境所以有了上面的这一句话 我们都知道平面图形是由一条条线段构成,所以我们就先实现线段的打印 1 //打印自定义长度的线段 2 #include 3 intmain() 4 {5 int i = 0; 6 intn; 7 while (~scanf("%d",&…

C语言图形化编程 【二】

C语言图形编程 二 3 基本贴图3.1 声明一个存储图片的变量3.2 图片的路径3.3 显示图片3.4 透明贴图 4 鼠标操作4.1 声明一个存储鼠标信息的变量4.2 获取鼠标4.3 分类讨论鼠标消息的来源 3 基本贴图 3.1 声明一个存储图片的变量 格式: IMAGE img; //类型 变量名(你要贴的图片的…

基于C语言的图形化编程软件,图形化编程工具

原标题:图形化编程工具 1.产品介绍 唯众图形化编程工具是一款基于拖拽式图形化设计的可视化编程工具库,通过拖拽式图形化编程完成程序设计。作为一种易于掌握的图像化编程环境,是编程初学者学习和掌握程序设计方法的有力工具。用图形化编程方式去理解程序语言,可以让学生更…

C语言:编程打印图形

题目 编程打印以下图形: 代码 #include "stdio.h"void main() {char ch = A;int i,j;for(i=

c语言图形时钟编程,c语言程序+图形编程——打造简易的时钟

全程代码小编就在这里发出来了哈,最终的效果图, // c语言+图形编程 电脑时钟 //包含头文件 #include #include #include void Draw_Dial();//绘制静态的表盘 void Draw_Hand(int hour, int minute, int secend); //绘制表针 //主函数 int main() {initgraph

C语言图形编程--俄罗斯方块制作(一)详解

效果图 用C语言实现俄罗斯方块&#xff0c;需要先解决下面几个问题&#xff1a; 1、如何用C语言绘制图形界面 EasyX图形库(http://www.easyx.cn)即TC的图形库在VC下的移植。 包含库#include <graphics.h> 先初始化图形窗口 initgraph(WINDOW_WIDTH, WINDOW_HIGH) ;WINDOW…

C语言图形代码:三角、金字塔、圣诞树、爱心

在C语言的学习过程中&#xff0c;我们熟练掌握循环以后就可以使用循环编写&#xff0c;我们喜欢的图形代码啦&#xff01; 下面我向大家分别展示四种使用C语言循环编写的代码。 后两种都可以用来给自己的女朋友展示喔 1.三角形 2.金字塔 3.圣诞树 4.爱心 &#xff08;1&#…

linux下c语言图形界面实现,「分享」C语言如何编写图形界面

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 贴吧内经常有人问C语言是不是只能用于字符终端界面开发,不能用于图形界面。大家也都有回答,需要其他的库。MFC,GTK,QT。 本人近期刚用GTK库加上纯C写成了第一个LINUX实用程序。现在与大家分享: 主界面程序gmaxtrix.c #includ…

c语言图形时钟编程,c语言+图形编程——打造浅易的时钟

全程代码小编就在这里发出来了哈 // c语言图形编程 电脑时钟 //包罗头文件 #include #include #include #define PI 3.141592654 void Draw_Dial();//绘制静态的表盘 void Draw_Hand(int hour, int minute, int secend); //绘制表针 //主函数 int main() { initgraph(640, 4…

简单c语言图形程序设计,c语言简单图形编程

c语言编程如何实现图形化? 如果你是说编写用户界面的C语言编程,那就应该学习平台编程.主流平台有windows,linux等. 楼主是领会到C得要点了.C不像JAVA和C#,它们才叫编写应用程序,因为它们的库直接可以编写出程序的应用部分(比如用户界面,调用系统资源等). 但是C语言不能叫做 c语…

C语言图形编程|设置位置

一、对光标位置进行修改 1、通过自定义函数来实现将光标移动到指定位置 void gotoxy(int x,int y) {HANDLE hCon;hCon GetStdHandle(STD_OUTPUT_HANDLE);COORD Pos;Pos.X x;Pos.Y y;SetConsoleCursorPosition(hCon,Pos); } 代码优化: void gotoxy(int x,int y) {COORD P…

C语言图形化编程

画折线图 #include<stdio.h> #include<conio.h> #include<graphics.h> #include<stdlib.h>void hDrawk(char c[]); void vDrawk(char c[]); void Drawfline(int b[]); int xs48,ys50;void hDrawk(char c[]) {int i,j65;line(65,360,565,360);for(i0;i&…

C语言图形化编程 【一】

C语言图形化编程 一 一、绘图窗口1.1 加载头文件1.2 创建一个窗口1.3 关闭窗口1.4 窗口坐标1.5 颜色1.6 设置颜色1.6.1 背景颜色1.6.2 线颜色1.6.3 文字颜色1.6.4 填充颜色 二、基本的绘图2.1 画点函数2.2 画线函数2.3 画矩形函数非填充(空心&#xff09;填充(实心)有边界线无边…

数据结构——图的五种种类【无向图-有向图-简单图-完全无向图-有向完全图】

目录&#xff1a; 一&#xff1a;无向图 1.定义 2.图形化解释 3.结合​表达式介绍 二&#xff1a;有向图 1.定义 2.图形化解释 3.结合​表达式介绍 有向图和无向图区别&#xff1a; 三&#xff1a;简单图 1.定义 2.图形化解释 四&#xff1a;完全无向图 1.定义 …

完全二分图

G <V,E> V – 》 元素顶点集 E --》 连线边集 V X ∪Y X中的任一顶点与Y中每一个顶点均有且仅有唯一的一条边相连&#xff0c;则称G为完全二分图或完全偶图。

构造完全图

咕咕咕 由于我好久都没有独立思考了&#xff08;抄了好久题解&#xff09;&#xff0c;思维什么的早没有了。 看完题只能想到一种暴力&#xff1a;遍历LCA 题目给出的是一个最小生成树&#xff0c;我们可以从边入手&#xff0c;把每条边所连的左右两个点分别看做一个集合&#…

图(一)

图论 结论&#xff1a; 1.无向完全图&#xff1a;在顶点数给定为n的情况下&#xff0c;边数达到最大的n(n-1)/2条边。 2.有向完全图&#xff1a;在顶点数给定为n的情况下&#xff0c;有向边数达到最大的n(n-1)条边。 3.树是图的特例&#xff1a;无环的无向图 4.生成树有可能不…

完全图的生成树

经典证明&#xff1a;Prfer编码与Cayley公式(转Matrix67) Cayley公式是说&#xff0c;一个完全图K_n有n^(n-2)棵生成树&#xff0c;换句话说n个节点的带标号的无根树有n^(n-2)个。今天我学到了Cayley公式的一个非常简单的证明&#xff0c;证明依赖于Prfer编码&#xff0c;它是对…

完全多部图

解题思想&#xff1a; 对于图中所有节点&#xff0c;如果不相连&#xff0c;按照题意&#xff0c;必须在一个集合里&#xff1b; 所以其实可以从第一个节点入手&#xff0c;找出与该点不相邻点的所有节点组成一个集合&#xff1b; 判断剩余所有点&#xff0c;如果不和该集合中所…