zoukankan      html  css  js  c++  java
  • 代码质量工具总结

    代码质量工具总结

    说到代码质量,这个是程序员职业生涯,至少是编码生涯的永久性话题;不同时期,见解也有不同。个人认为,不存在什么绝对错误和绝对正确,当然那种写出明显的空指针异常排除在外。有时候编码质量是一个见仁见智,个人的习惯问题。但是,编码也是群体活动,有个共同遵守的规范是必须的,也是必要的。
    写在前面,本文所述的所有的工具,基本上都是考虑到 java 语言层面,当然这些工具也可能适用其他语言。

    代码质量检查工具

    PMD

    代码库一直在持续更新的代码质量检查工具,通过静态分析获知代码错误,即无需运行Java程序的情况下就报告错误。提供各大 IDE 插件,提供 maven-pmd-plugin插件。最新版的 java 语言质量检查规则。支持用户自定义规则。下面列出一些检查规则:

    检查规则:

    • If、While、IfElse、For表达式必须使用{},无论有多少语句;
    • 如果方法返回boolean,那么注意避免不必要的if…then…else语句;
    • 避免if语句嵌套过深(降低代码可读性);
      解决办法:建议if嵌套不要超过2层。使用工具方法封装更多的if语句或者把嵌套的if表达式放到同一个层次中;
    • 忽略大小写进行字符串比较时,使用String.equalsIgnoreCase,不要使用String.toLowerCase。前者有更好的性能,而且还可以避免后者带来的本地化问题;
    • 避免方法级的同步,块级别的同步可以确保内含真正需要同步的代码;
    • 使用集合类的isEmpty方法;
      java.util.Collection类的isEmpty方法提供判断一个集合类是否包含元素。不要是使用size()和0比较来重复类库已经提供的方法。原则:尽量复用,充分利用已有的资源,不要重复造轮子。
    • 没有使用的就去掉,保持代码的干净、整洁,包括:没有使用的私有成员、本地变量、私有方法、方法参数(参数定义,但方法内没有使用此参数)
    • 构建StringBuffer或StringBuilder时,如果知道长度,请指定,这样性能更好。不指定,则默认长度是16,这样当长度不够时,就会有扩容的动作。
    • 如果本地变量只被赋值一次,或者方法参数从来不会被重新赋值,可以把它声明为Final;
    • 如果想由数组构建List,请使用Arrays.asList;
    • 数组复制,请使用System.arraycopy,别用循环;
    • ""+123 的方式把数字转换为String,不够高效;
    • 避免代码中出现各种"空"的语句:空Catch,If,while,try,finally,switch,Synchronized,static块;
    • 重复的代码:拷贝/粘贴代码意味着拷贝/粘贴bugs;
    • 循环体创建新对象:尽量不要再for或while循环体内实例化一个新对象;
    • 资源关闭:Connect,Result,Statement等使用之后确保关闭掉;
      还有其他很多……
      用户还可以自定义规则,检查Java代码是否符合某些特定的编码规范。例如可以编写一个规则,找出所有创建Thread和Socket对象的操作。

    基本使用

    命令行方式:java -jar pmd-6.8.0.jar /your_project/src text rulesets/unusedcode.xml,更详细的命令行参数使用-help查看即可得知。
    idea集成pmd,搜索插件安装即可。

    工作原理

    PMD的核心是JavaCC解析器生成器。PMD结合运用JavaCC和EBNF(扩展巴科斯-诺尔范式,ExtendedBackus-Naur Formal)语法,再加上JJTree,把Java源代码解析成抽象语法树(AST,Abstract SyntaxTree)。不过,为了让解析器承认这些普通的文本是合法的Java代码,它们必须符合某种特定的结构要求。这种结构可以用一种称为EBNF的句法元语言表示,通常称为“语法”(Grammar)。JavaCC根据语法要求生成解析器,这个解析器就可以用于解析用Java编程语言编写的程序。
    实际运行中的PMD还要经过JJTree的一次转换。JJTree是一个JavaCC的插件,通过AST扩充JavaCC生成的解析器。AST是一个Java符号流之上的语义层。有了JJTree,语法分析的结果不再是“System, ., out, ., .println”之类的符号序列,而是一个由对象构成的树型层次结构。

    FindBugs

    官网:http://findbugs.sourceforge.net/
    最后一次更新是06 March, 2015,不算太过时。

    简介

    FindBugs是一个java byte code静态分析工具,检测出Java程序中上百种潜在的不同类型的错误。不注重style及format,注重检测真正的bug及潜在的性能问题,尤其注意尽可能抑制误检测(false positives)的发生。除了作为单独的组件安装,还可以集成IDE,以及maven。其检测输出结果可以是XML或文本形式的。支持自定义配置检查规则(做哪些检查,不做哪些检查),校验规则(用户自定义特定的bug模式需要继承它的接口,编写自己的校验类)。

    规则

    FindBugs检查类或者 JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题。根据最新的页面bugDescriptions,自带88种Bad practice,149种Correntness,3种Experimental,2种Internationalization,18种Malicious code vulnerability,46种Multithreaded correntness,29种Performance,11种Security,80种Dodgy code。
    这个页面能看到很多缩写,缩写的意义,以及不规范的和建议的规范的代码的解释。多看几遍,对于规范自己的coding style非常有帮助。

    IDEA安装FindBugs非常容易。安装完之后,可能需要设置提高检查的级别,因为可能检查规则过于严格。

    checkstyle

    CheckStyle检查代码是否符合制定的规范。CheckStyle 检查是基于源码的,所以不需要编译,执行速度快。
    CheckStyle的主要流程是:

    1. 对Java文件进行词法语法分析,生成语法树。
    2. 载入配置文件(checkstyle-metadata.xml以及自定义的配置文件)register check事件。
    3. 按照深度优先遍历对语法树进行解析,按照注册的事件,在到达某些节点( AST ) 时进行style检查(AST,A child-Sibling Tree,是语法树中的某个节点,其类型在TokenTypes类中定义。)
    4. 自定义Style的检查,就是在第二步设定的。实现com.puppycrawl.tools.checkstyle.api.Check类,重载其中的两个方法: public int[] getDefaultTokens() 和public void visitToken(DetailAST ast)。这两个方法的含义为,在遍历语法树的过程中,每当到达getDefaultTokens函数所返回的AST类型,程序就进入visitToken进行具体的检查和分析,即真正的分析检查过程是在visitToken中实现的。

    CheckStyle有针对不同IDE和构建工具的各种插件,如 maven-checkstyle-plugin 插件,其简单的参考配置:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-checkstyle-plugin</artifactId>
        <version>3.0.0</version>
        <configuration>
        	<!--内置4种规范:config/sun_checks.xml、config/maven_checks.xml、config/turbine_checks.xml、config/avalon_checks.xml、其中sun_checks.xml为默认值。修改默认配置-->
            <configLocation>config/maven_checks.xml</configLocation>
            <!--启用自定义规范文件-->
            <!--<configLocation>${basedir}/src/config/custom_checkstyle.xml</configLocation>-->
        </configuration>
        <executions>
            <execution>
                <id>checkstyle</id>
                <phase>validate</phase>
                <goals>
                    <goal>check</goal>
                </goals>
                <configuration>
                    <failOnViolation>true</failOnViolation>
                </configuration>
            </execution>
        </executions>
    </plugin>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    定义在maven lifecycle的validate阶段执行check task,并且如果发现有违反标准的情况就会fail当前的build。运行checkstyle检查:mvn checkstyle:checkstyle

    跳过对指定文件的某些检查
    方法一:suppression:忽略指定文件的问题检查,不推荐;
    方法二:新建一个checkstyle-suppressions.xml文件,增加suppressions配置项:

    <?xml version="1.0"?>
    <!DOCTYPE suppressions PUBLIC
            "-//Puppy Crawl//DTD Suppressions 1.0//EN"
            "http://www.puppycrawl.com/dtds/suppressions_1_0.dtd">
    <suppressions>
        <suppress checks="LineLengthCheck"
                  files="SessionMessageSource.java"/>
    </suppressions>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    <suppressionsLocation>${basedir}/src/config/checkstyle-suppressions.xml</suppressionsLocation>
    然后在配置文件里面可以定义一系列可用的模块,每一个模块提供严格程度(强制的,可选的…)可配置的检查规则。规则可以触发通知(notification),警告(warning)和错误(error)。
    附:
    google-checkstyle

    特点:

    1. 它可以有效的帮助我们检视代码以便更好的遵循代码编写标准,特别适用于小组开发时彼此间的样式规范和统一。
    2. Checkstyle提供高可配置性,以便适用于各种代码规范,所以除了使用它提供的几种常见标准之外,你也可以定制自己的标准。
    3. Checkstyle提供支持大多数常见IDE的插件,大部分插件中就含有最新的Checkstyle。
    4. Checkstyle可以检查代码的很多方面,从传统观点看,它主要是用来检查代码层面的,自从第三版以后,它的内部架构作了重大改变,很多其它意图的检测加了进来,现在Checkstyle可以检查像类设计的问题,重复代码,如锁的双重检查的bug模式。

    JArchitect

    JArchitect,一款静态分析工具,使用一种基于Linq(CQLinq)的代码查询语言,像查询数据库那样来查询代码。最新版v2019.1下载地址,可以把许多其他静态分析工具的输出结果包含进来,然后使用CQLinq做查询,提供CI/CD工具集成功能,提供报表功能。付费工具,功能很强大。
    在这里插入图片描述

    简单使用:
    解压缩,双击VisualJArchitect.exe,新建工程,选择一个想要被分析的项目,然后点击开始分析即可。
    在这里插入图片描述
    从分析结果面板可见其功能强大。

    CQLinq:
    类似SQL语法,有智能提示,并且给出近乎实时的语法检查和查询结果;

    SonarLint & SonarQube

    官网:https://www.sonarqube.org/
    slogan: Continuous Inspection

    简介

    必须要指出 SonarQube 是开源的代码质量管理平台,以 web 页面形式(即Sonar Dashboard)可视化形式检查代码质量;SonarLint 是 SonarQube 提供的插件,可以安装在各个 IDE 工具。
    后来者居上,SonarQube是一个集大成者,允许配置安装插件,比如前文提到的 Findbugs, PMD 和 CheckStyle,基于这些插件的代码质量检查规则多达上千条,已经可以覆盖代码质量的绝大多数方面,更新版本的功能更多。

    在这里插入图片描述

    Sonar 可以从七个维度检测代码质量:

    1. 代码规则——sonar可以通过PMD,CheckStyle,Findbugs等等代码规则检测工具规范代码编写;
    2. 潜在的缺陷——通过PMD,CheckStyle,Findbugs 等代码规则检测工具检测出潜在的缺陷;
    3. 复杂度——无论对于类还是方法,都不宜过长,长意味着复杂,问题丛生……。
    4. 重复——sonar会检查重复片段,此时需要重构并提取共有逻辑;
    5. 注释不足或者过多——关键的代码片段不能没有注释,注释得简洁有意义,且需要及时更新;
    6. 单元测试——sonar可以很方便地统计并展示单元测试覆盖率;
    7. 架构与设计——通过sonar可以找出循环,展示包与包、类与类之间相互依赖关系,可以检测自定义的架构规则 通过sonar可以管理第三方的jar包,可以利用LCOM4检测单个任务规则的应用情况, 检测耦合。

    特性:

    • 通过插件扩展
      支持新的编程语言、添加规则引擎、计算更复杂的度量指标,这些都可以借助强大的插件扩展机制。通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具,比如pmd-cpd、check-style、find-bugs、Jenkins。通过不同的插件对这些结果进行再加工处理,通过量化的方式度量代码质量的变化,从而可以方便地对不同规模和种类的工程进行代码质量管理。
    • 支持多种编程语言
      借助插件,支持各种主流编程语言;
    • 集成CI
      同时 Sonar 还对大量的持续集成工具提供接口支持,可以很方便地在持续集成中使用 Sonar
    • 代码质量周边
      提供插件,规则、告警、例外……都可以在线配置。通过自己的数据库,SonarQube不仅仅是展示各项指标的综合结果,同时也结合历史质量数据。
    • 国际化
      对国际化以及报告文档化也有良好的支持。

    IDEA 安装插件 Sonar Lint

    安装 Sonar Lint 插件需要重启,然后打开other setting——SolarLint——General Settings,输入sonarqube的地址,一般公司会搭建内网平台,在 Server URL 里面添加这个地址,按需输入用户名/密码,测试连接,连接成功即可使用。

    sonar平台搭建

    非常类似于Jenkins,sonar提供war包,下载解压,配置一下数据库(默认MySQL,本地或者远程都行),然后启动脚本(bat或sh)。

    Alibaba coding guiding

    提供 IDEA 插件 Alibaba java coding guideline,方便集成在IDEA,实时发现并修改不规范代码。有一份详细的 pdf 文档《码出高效:阿里巴巴 Java 开发手册》解释编码规范;比较好的是:针对插件检查出来的不规范,有详细的解释。最近还有一本书《码出高效:Java开发手册》,纸质书定价99元,抢钱啊;土豪可忽视。
    链接:
    阿里巴巴编码规范(JAVA)认证考后感

    代码审查(code-review)工具

    上面的工具仅仅只是编码规范的自动化检查工具;但是事实上,业务开发,仅仅只有这些规范检查工具是远远不够的,毕竟代码是写给人看的,写给同事,写给离职后的维护者看的。所以,还需要在此基础之上添加一道代码审查工具,帮助人工审查代码,检查可以优化的编码块。

    • Review Board
    • jArchitect
    • RhodeCode
    • Codebrag
    • Crucible
    • Malevich
    • Gerrit

    Review Board

    Review Board起源于VMware的一些开发者。它基于Django,你可以把它安装在自己的服务器上,工作流和Rietveld极为类似。提供在diffs里进行语法彩色编码,使得代码阅读变得简便。此外,它还实现基于Lucene的搜索来帮助管理较大的diffs组。提供 IDEA 插件、邮件支持,有 web 端,使用体验良好。
    Review Board在审查补丁(Patch)方面表现完美。一个叫做“提交审查”的工具被用来和SCM系统进行连接(支持各大VCS 如 SVN,DVCS 工具如 Git 等),可以允许你请求一个将被提交的修改的审查。用户基础页面将这个过程描述如下:

    1. 你在本地检出的代码上做些修改。
    2. 你通过公布diff、编写描述和选择一些审查者来创建一个审查请求。
    3. 你在审查请求中点击“发布”并等待你的审查者看到它。
    4. 审查者或者其他人看到你的审查请求,提出改进意见。
    5. 根据他们的评论更新你的代码。
    6. 公布更新后的diff,以及对他们评论的解答以指明你修改什么(或者你要说明为什么你不打算按照他们的建议修改代码)。
    7. 将修改提交到仓库中。
    8. 在审查请求中点击“设置为已提交”来从其他人的面板中移除你的审查请求。

    Gerrit

    Gerrit 实际上一个Git服务器,它为在其服务器上托管的Git仓库提供一系列权限控制,以及一个用来做Code Review (核心功能)的Web前台页面。实际上此处讲解的 Gerrit 的 code review 以及 GitLab Changes 的 code review 功能,都是基于 git hook 原理实现的。留坑:有时间,好好研究一下 Git hook。
    登录Gerrit后在Projects–>List,选择工程,进入该工程的General界面。
    在这里插入图片描述
    clone 就是常规的 GitHub 页面的 git clone,此处推荐使用后者,即 clone with commit-msg hook;后面是协议,一般选择 SSH:

    git clone ssh://awesome.me@code.awesome.com:2018/Qyhj/Service/PaymentService && scp -p -P 2018 awesome.me@code.awesome.com:hooks/commit-msg PaymentService /.git/hooks/
    拷贝以上命令在自己本地 Git 命令行窗口执行即可拉取库代码。

    todo

    GitLab Changes

    Changes 是一种类似 gerrit changes 的code review方式。使用方法如下:

    1. 需要在git clone时选择 with commit-msg,如图:
      在这里插入图片描述
      会将commit-msg hook文件一起 clone 到本地;
    2. 随后通过git addgit commit命令修改 & 提交代码到本地,push时记住需要执行git push origin HEAD:refs/for/master
    3. 上面的git push会给出此次提交的git diff,即change页面地址,打开页面一目了然地查看 diff 。
    4. review代码,同意可以通过点Accept按钮将代码合并到远端仓库,不同意可以点击close按钮关闭掉change;
    5. 如果review代码需要多个人review后才能合并,可以在project settings页面配置;
    6. 如果review不通过,即close 掉之后,需要继续修改本地文件,然后执行同样的 git push 命令产生新的change,并打开链接,需要 approver 执行 approve 后才可以进行Accept操作;
    7. 合并后如果发现不对劲,可以通过revert功能进行回退。

    其他还有一些细节,可以自己去摸索。
    总结:Gitlab 的 changes功能是仿照gerrit的code review功能引入的,其中 related_changes、patch_sets 的概念和gerrit基本一致,rebase、revert等功能用法也类似。注意:如果change进行rebase操作,本地更新代码时需添加–rebase参数,具体为:
    git pull --rebase
    参考来源:内网类 blog 系统;

    实施

    上面讲了不少工具,可是规范毕竟是规范,不实施起来,强硬提交(–force or --hard)也是无奈。所以有必要设置一个关卡,不满足则不让提交或者失败;可以从两个地方加以控制实施。

    VCS 服务端

    在 version control system 服务端(如git,svn服务端)实施,如果不达标则拒绝提交(允许提交到其他分支以便保留工作成果,但是不能 merge 到 master 或者 release branch)。
    提交代码前自动执行检查,想到Git commit hook,比如 pre-commit hook

    #!/bin/sh
    # From gist at https://gist.github.com/chadmaughan/5889802
    # stash any unstaged changes
    git stash -q --keep-index
    # run the tests with the gradle wrapper
    ./gradlew clean build
    # store the last exit code in a variable
    RESULT=$?
    # unstash the unstashed changes
    git stash pop -q
    # return the './gradlew build' exit code
    exit $RESULT
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    将该脚本拷贝到项目 .git/hooks/下,在执行git commit的时自动触发检查,如果检查失败则提交失败。.git 并不能提交到远程代码仓库,除人工分发和拷贝外,有没有更好的方式在团队中共享这个机制呢?
    可以把pre-commit纳入版本控制(如config/pre-commit),再使用构建工具的扩展机制来自动完成拷贝工作,这样可以间接实现git hooks的团队间共享。缺点:没有使用 gradle,使用 maven 怎么做?

    # build.gradle
    task installGitHooks(type: Copy) { //将pre-commit拷贝到指定位置
      from new File(rootProject.rootDir, 'config/pre-commit')
      into {
        new File(rootProject.rootDir, '.git/hooks')
      }
      fileMode 0755
    }
    build.dependsOn installGitHooks //设置执行build任务时会自动触发installGitHooks任务
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    CI/CD 服务端

    利用 CI/CD 服务端,在 Jenkins 构建(Jenkins 集成 checkstyle 或者 sonarqube)或者随后的部署阶段检查代码质量,不满足则触发失败。或者如果使用 maven-checkstyle-plugin,则可以随时触发检查。

    参考
    1
    如何更好地利用Pmd、Findbugs和CheckStyle分析结果

  • 相关阅读:
    基础系列(3)—— 高级数据类型
    ASP.NET MVC5 基础系列(3)——视图
    JSP学习笔记
    Tomcat学习笔记
    Tomcat学习笔记
    Tomcat学习笔记
    Tomcat学习笔记
    Tomcat学习笔记
    MySQL学习笔记(5)
    MySQL学习笔记(4)
  • 原文地址:https://www.cnblogs.com/ios9/p/14040051.html
Copyright © 2011-2022 走看看