关注不迷路

1.前言

工作中难免会遇到维护别人代码的情况,那么首先就得看懂别人写的代码。如果对方写的代码混乱臃肿,维护成本必然很高,如果对方写的代码优雅清晰,那维护的人看起来必然心情愉悦。正所谓“前人栽树,后人乘凉;前人埋坑,后人骂娘”。

代码首先是给人看的,其次才是给机器看到,如何编写出任何人都看到懂的代码?答案是制定规范!

每个公司都会有自己的编码规范,但是往往的情况是赶项目进度或者懒惰或者个人水平习惯等原因,加上没有code review,最后代码就写的千奇百怪了。原因就在于规范是有了,但是没人遵守。所以,编码规范需要强制执行,交给工具来强制执行。

本文将通过介绍java静态代码检查工具PMD、阿里巴巴p3c开源项目到最后编写自定义编码规约来学习如何规范代码的编写。

2.PMD静态代码扫描

2.1.PMD官网

https://pmd.github.io/

2.2.概述

PMD是一种开源分析Java代码错误的工具。它通过静态分析获知代码错误。也就是说,在不运行Java程序的情况下报告错误。PMD附带了许多可以直接使用的规则,利用这些规则可以找出Java源程序的许多问题,例如:

  • 潜在的bug:空的try/catch/finally/switch语句

  • 未使用的代码:未使用的局部变量、参数、私有方法等

  • 可选的代码:String/StringBuffer的滥用

  • 复杂的表达式:不必须的if语句、可以使用while循环完成的for循环

  • 重复的代码:拷贝/粘贴代码意味着拷贝/粘贴bugs

  • 循环体创建新对象:尽量不要再for或while循环体内实例化一个新对象

  • 资源关闭:Connect,Result,Statement等使用之后确保关闭掉

此外,用户还可以自己定义规则,检查Java代码是否符合某些特定的编码规范。例如,你可以编写一个规则,要求PMD找出所有创建Thread和Socket对象的操作。

2.3.工作原理

PMD的核心是JavaCC解析器生成器。PMD结合运用JavaCC和EBNF(扩展巴科斯-诺尔范式,Extended Backus-Naur Formal)语法,再加上JJTree,把Java源代码解析成抽象语法树(AST,Abstract Syntax Tree)

从根本上看,Java源代码只是一些普通的文本。不过,为了让解析器承认 这些普通的文本是合法的Java代码,它们必须符合某种特定的结构要求。这种结构可以用一种称为EBNF的句法元语言表示,通常称为“语法” (Grammar)。JavaCC根据语法要求生成解析器,这个解析器就可以用于解析用Java编程语言编写的程序。

2.4.规则分类

  • 最佳实践:公认的最佳实践的规则。

  • 代码风格:这些规则强制执行特定的编码风格。

  • 设计:帮助您发现设计问题的规则。

  • 文档:这些规则与代码文档有关。

  • 容易出错的规则:用于检测被破坏的、非常混乱的或容易发生运行时错误的结构的规则。

  • 多线程:这些规则在处理多个执行线程时标记问题。

  • 性能:标记存在性能问题的代码的规则。

  • 安全:显示潜在安全缺陷的规则。

2.5.编写PMD自定义规则

  • https://pmd.github.io/pmd-5.4.1/customizing/howtowritearule.html

  • https://testerhome.com/topics/4918

  • http://www.w3school.com.cn/xpath/index.asp

3.阿里巴巴Java开发规约插件p3c

3.1.GITHUB地址

https://github.com/alibaba/p3c

3.2.概述

阿里巴巴p3c项目包含三个部分:

  • p3c-pmd,提供大部分规则实现,基于PMD框架开发,如果想实现自己的规则,可以基于该模块开发(该模块基于maven编译打包)

  • IntelliJ IDEA插件,即idea-plugin模块(该模块基于gradle编译打包)

  • Eclipse插件,即eclipse-plugin,本文不介绍

3.3.阿里编码规约IDEA插件使用

传送门:https://github.com/alibaba/p3c/wiki/IDEA%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3

4.基于p3c编写自定义编码规则

4.1.自定义规则

假设现在需要开发这么一个规则:方法请求参数列表不允许超过(含)5个

4.2.开发步骤

4.2.1.找出问题代码,使用pmd图形化工具解析成抽象语法树

代码示例:

package org.p3c.demo;public class Demo {public void methodA(int a) {}public void methodB(int a, int b, int c, int d, int e) {}
}

将源码放入Source Code框,点击Go按钮,解析结果显示在左下框

4.2.2.分析抽象语法树

可以看到,整棵树的根节点是CompilationUnit,即编译单元,代表每个java源文件。我们首先要找到所有的方法声明,根据树节点名称大概也能看出来是MethodDeclaration,点击相应的节点,看看光标是否定位到源码方法声明位置。

仔细分析MethodDeclaration节点,可以看到他有以下几个直接子节点:ResultType、MethodDeclarator、Block,即返回类型、方法声明、方法体

MethodDeclarator是我们想找的节点XPATH表达式可以这么写:

//CompilationUnit//MethodDeclarator

验证表达式是否正确,将它写到PMD图形界面XPATH Query框中,点击Go按钮

接下来,我们需要找到每个方法对应的参数列表,参数列表节点是方法节点的直接子节点,完整XPATH表达式为:

//CompilationUnit//MethodDeclarator/FormalParameters

获取到参数列表节点后,我们查看该节点的属性,找出参数个数的属性,观察可以发现是ParameterCount属性。

到现在为止,抽象语法树已经分析完,我们知道这么找出代码中参数列表大于等于5个的方法了。

4.2.3.p3c-pmd项目编写自定义代码规则

打开阿里p3c-pmd工程,开始编写我们的自定义规则。

阿里已经写了很多规则,我们现在要编写的规则属于面向对象范畴,可以把规则写到opp包下,新建一个规则类MethodParameterCountRule,继承自AbstractAliRule,重写 visit方法:

package com.alibaba.p3c.pmd.lang.java.rule.oop;import com.alibaba.p3c.pmd.lang.java.rule.AbstractAliRule;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTFormalParameters;import java.util.List;/*** 方法参数列表个数不宜过长** @auther qingjian.wu* @create 2018-01-27 14:59*/
public class MethodParameterCountRule extends AbstractAliRule{private static final String METHOD_XPATH = "//MethodDeclarator";private static final Integer PARAMETER_COUNT_LIMIT = 5;@Overridepublic Object visit(ASTCompilationUnit node, Object data) {try {// 找到所方法节点List<Node> methodNodes = node.findChildNodesWithXPath(METHOD_XPATH);if (methodNodes != null && methodNodes.size() > 0) {for (Node methodNode : methodNodes) {// 找到每个方法的参数列表声明List<ASTFormalParameters> formalParameters = methodNode.findChildrenOfType(ASTFormalParameters.class);if (formalParameters.get(0).getParameterCount() >= PARAMETER_COUNT_LIMIT) {// 违反规则提示信息,第二个参数是提示信息位置,第三个参数是提示信息key,第四个参数用来替换提示信息// 中的占位符,这里获取的节点image属性就是方法名称addViolationWithMessage(data, methodNode,"java.oop.MethodParameterCountRule.violation.msg",new Object[]{methodNode.getImage()});}}}} catch (Exception e) {e.printStackTrace();}return super.visit(node, data);}
}

4.2.4.p3c-pmd项目配置规则

将编写好规则配置到ali-oop.xml文件中

<rule name="MethodParameterCountRule"language="java"message="java.oop.MethodParameterCountRule.rule.msg"class="com.alibaba.p3c.pmd.lang.java.rule.oop.MethodParameterCountRule"><!--级别,1强制,2推荐,3参考--><priority>1</priority><example><![CDATA[
Negative example:public void methodB(int a, int b, int c, int d, int e) {}
]]></example><example><![CDATA[
Positive example:public void methodA() {}
]]></example></rule>

4.2.5.p3c-pmd项目编写提示信息

上两步使用的提示信息和规则信息需要编写到message.xml配置文件中,message_en.xml中是英文提示,这里就先不演示了

<entry key="java.oop.MethodParameterCountRule.violation.msg"><![CDATA[方法【%s】参数列表过长。 ]]></entry><entry key="java.oop.MethodParameterCountRule.rule.msg"><![CDATA[说明:方法参数列表不允许超过(含)5个,建议封装到一个对象中。]]></entry>

4.2.6.单元测试

编写测试样例,将要测试的源代码写到test目录对应的xml文件中

<?xml version="1.0" encoding="UTF-8"?>
<test-data><code-fragment id="测试样例"><![CDATA[package org.p3c.demo;public class Demo {public void methodA(int a) {}public void methodB(int a, int b, int c, int d, int e) {}}]]></code-fragment><test-code><!-- 预期问题个数 --><expected-problems>0</expected-problems><code-ref id="测试样例" /></test-code>
</test-data>

编写单元测试

运行单元测试,因为样例代码中methodB不符合规范,但是我们预期问题个数写的是0,所以单元测试会不通过:

4.3.配置插件

4.3.1.p3c-pmd打包安装到本地maven仓库

先把用不到的插件maven-javadoc-plugin和maven-gpg-plugin注释掉,然后运行mvn命令:

mvn -DskipTests=true clean install

4.3.2.idea-plugin项目打包插件

idea-plugin项目基于gradle构建,配置根目录下build.gradle,让构建使用本地私有maven仓库构建

然后运行开始gradle构建:

clean buildDependents build

打包成功后会在idea-plugin\p3c-idea\build\distributions\目录下生成Alibaba Java Coding Guidelines-1.0.0.zip文件,这个就是我们加入了自己拓展阿里开发规约的插件,IDEA中安装此插件

Settings->Plugins->Install plugin from disk

4.3.3.IDEA中使用编码规约插件

安装完插件重启IDEA,用之前的代码测试下插件是否生效。

右键点击“编码规约扫描”

结果:

5.Maven打包加入PMD校验

到目前为止,我们已经做到了能在开发阶段实时校验自己的代码了,最后我们需要把规约检查加入到代码打包中,这样才能做到部署到生产环境的代码都是符合规范的,如果不符合规范,打包会失败。

考虑到大多数项目使用maven管理,可以把自定义pmd规则整合到maven,这样就可以使用maven校验代码规则了

在maven项目中加入pmd插件,配置插件在package阶段执行。通常我们的项目都有一个公共的父pom,那将插件加入到父pom中就行

<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-pmd-plugin</artifactId><version>3.8</version><configuration><rulesets><ruleset>rulesets/java/ali-comment.xml</ruleset><ruleset>rulesets/java/ali-concurrent.xml</ruleset><ruleset>rulesets/java/ali-constant.xml</ruleset><ruleset>rulesets/java/ali-exception.xml</ruleset><ruleset>rulesets/java/ali-flowcontrol.xml</ruleset><ruleset>rulesets/java/ali-naming.xml</ruleset><ruleset>rulesets/java/ali-oop.xml</ruleset><ruleset>rulesets/java/ali-orm.xml</ruleset><ruleset>rulesets/java/ali-other.xml</ruleset><ruleset>rulesets/java/ali-set.xml</ruleset></rulesets><printFailingErrors>true</printFailingErrors><!--扫描级别,小于等于这个级别的错误代码将不通过扫描。不配默认是5--><minimumPriority>1</minimumPriority></configuration><executions><execution><phase>package</phase><goals><goal>check</goal></goals></execution></executions><dependencies><dependency><groupId>com.alibaba.p3c</groupId><artifactId>p3c-pmd</artifactId><version>1.3.3</version></dependency></dependencies></plugin></plugins></build>

如果存在不符合规范代码打包将失败:

关于maven pmd插件更详细介绍参考官网

6.总结

本文篇幅确实有点长,看懂需要有点耐心。不过其实也挺简单,关键点就是分析抽象语法树,找出问题代码节点,剩下的工作就很简单了。

PMD也有局限性,比如只能校验java源文件,对于XML等配置规约就没辙了。还有最最重要的,代码逻辑等关键性问题是没法校验的,也没法做。PMD只是一定程度上规范了我们的代码,要写出优雅的代码,还得多思考多实践呐。

来源:blog.csdn.net/u014513883/

article/details/79186893

PS:如果觉得我的分享不错,欢迎大家随手点赞、在看。

关注公众号:Java后端编程,回复下面关键字

要Java学习完整路线,回复  路线 

缺Java入门视频,回复: 视频 

要Java面试经验,回复  面试 

缺Java项目,回复: 项目 

进Java粉丝群: 加群 

PS:如果觉得我的分享不错,欢迎大家随手点赞、在看。

(完)

加我"微信" 获取一份 最新Java面试题资料

请备注:666,不然不通过~

最近好文

1、Kafka 3.0重磅发布,弃用 Java 8 的支持!

2、你只会用 ! = null 判空?嘿嘿!

3、这次,Swagger-ui遇到对手了!

4、一个基于Spring Boot+Vue+Redis的物联网智能家居系统

5、本机号码一键登录原理与应用

最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:关注公众号并回复 java 领取,更多内容陆续奉上。

明天见(。・ω・。)ノ

扩展阿里巴巴 Java 开发规约插件,打造团队专属风格!相关推荐

  1. IDEA阿里巴巴Java开发规约插件使用

    IDEA阿里巴巴Java开发规约插件使用 在 10月14日上午9:00  阿里巴巴于在杭州云栖大会<研发效能峰会>上,正式发布<阿里巴巴Java开发手册>扫描插件,该插件在扫描 ...

  2. android 阿里巴巴插件,阿里巴巴 Java开发规约插件使用 (同样适用Android)

    Alibaba于在杭州云栖大会<研发效能峰会>上,正式发布<阿里巴巴Java开发手册>扫描插件,该插件在扫描代码后,将不符合<手册>的代码按Blocker/Crit ...

  3. Eclipse安装阿里巴巴Java开发规约插件

    点击Help ----->> Install New Software... 然后进入如下页面: 点击Add... name随便起 输入地址如下:https://p3c.alibaba.c ...

  4. 阿里巴巴Java开发规约插件p3c

    参考链接:https://www.cnblogs.com/han-1034683568/p/7682594.html

  5. 《阿里巴巴Java开发规约》插件全球首发!

    经过247天的持续研发,阿里巴巴于10月14日在杭州云栖大会上,正式发布众所期待的<阿里巴巴Java开发规约>扫描插件! 插件全球首发仪式,大牛云集 阿里巴巴大牛天团倾力助阵:毕玄.玄难. ...

  6. 阿里巴巴Java开发规约IDEA插件使用

    阿里巴巴Java开发规约IDEA插件使用自发布之日起就兴致勃勃的装上使用了,对没有自己编码规范的团队来说使用起来很方便,对提高大家的编程素养还是很有好处的.分享一下idea的使用方法.希望阿里能继续维 ...

  7. 《阿里巴巴Java开发规约》插件使用详细指南

    阿里巴巴于10月14日在杭州云栖大会上,正式发布众所期待的<阿里巴巴Java开发规约>扫描插件.今天,阿里妹为大家详细介绍一下IDEA插件与Eclipse插件的安装使用. 插件下载地址 h ...

  8. idea java 阿里巴巴_AS 阿里巴巴Java开发规约 CheckStyle-IDEA

    Alibaba Java Coding Guidelines 简介 Alibaba Java Coding Guidelines 是阿里巴巴发布的基于 IDEA 的 Java 开发规约扫描插件. 经过 ...

  9. idea安装阿里巴巴java规范插件(代码质量管理)安装和使用

    一.插件发布背景 2017年10月14日上午9:00  阿里巴巴于在杭州云栖大会<研发效能峰会>上,正式发布<阿里巴巴Java开发手册>扫描插件,该插件在扫描代码后,将不符合& ...

最新文章

  1. 基于AWS-ELK部署系统日志告警系统
  2. dll文件32位64位检测工具以及Windows文件夹SysWow64的坑
  3. [AGC018 B] Sports Festival 解题报告
  4. js----map和对象的区别
  5. 两对光纤收发器用网线连接_为什么现在的人不喜欢用网线,反而更爱用光纤来传输呢?涨知识了...
  6. flink CompactingHashTable源码解析
  7. Python学习之==数组(二)
  8. c语言中汉字属于什么类型_练字应该练什么之:汉字基本结构的类型
  9. 猫连接路由器路由下连七台电脑,为啥每台电脑手动设ip才有网?
  10. asp网站服务器软件,asp服务器软件
  11. String split分隔符总结
  12. 深度强化学习DQN(Deep Q Network)原理及例子:如何解决迷宫问题,附源码
  13. paip.提升程序稳定性---最佳实践
  14. Hadoop集群的搭建(结束)——修改hadoop配置文件以及启动集群服务
  15. Edison 蓝牙模块 学习笔记
  16. 几种常用的分布式定时任务
  17. 如何使用Bootbox ?
  18. 学习笔记-极客时间 玩转 git 三剑客 课程记录
  19. 你真的知道如何选择内存条吗?
  20. 电脑族保护视力的窍门

热门文章

  1. 假的肯德基活动链接的分析
  2. 【理论篇】是时候彻底弄懂BERT模型了(收藏)
  3. Java--for循环之双层循环嵌套 执行流程
  4. vue element表格某一列内容过多,超出省略号显示
  5. 用C语言读写文本文件
  6. 项目的组织结构(P140)
  7. 多目标跟踪(MOT)入门综述
  8. 修仙录4.2 最终章
  9. TCP ISN、三次握手、四次挥手
  10. Android NDK 开发环境搭建(二)----来源http://www.cnblogs.com/zdz8207/archive/2012/11/27/android-ndk-install.htm