同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

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

同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
代码首先是给人看的 , 其次才是给机器看到 , 如何编写出任何人都看到懂的代码?答案是制定规范!
每个公司都会有自己的编码规范 , 但是往往的情况是赶项目进度或者懒惰或者个人水平习惯等原因 , 加上没有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开发规约插件p3c3.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插件使用文档
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按钮 , 解析结果显示在左下框
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
4.2.2.分析抽象语法树可以看到 , 整棵树的根节点是CompilationUnit , 即编译单元 , 代表每个java源文件 。我们首先要找到所有的方法声明 , 根据树节点名称大概也能看出来是MethodDeclaration , 点击相应的节点 , 看看光标是否定位到源码方法声明位置 。
仔细分析MethodDeclaration节点 , 可以看到他有以下几个直接子节点:ResultType、MethodDeclarator、Block , 即返回类型、方法声明、方法体
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
MethodDeclarator是我们想找的节点XPATH表达式可以这么写:
//CompilationUnit//MethodDeclarator验证表达式是否正确 , 将它写到PMD图形界面XPATH Query框中 , 点击Go按钮
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
接下来 , 我们需要找到每个方法对应的参数列表 , 参数列表节点是方法节点的直接子节点 , 完整XPATH表达式为:
//CompilationUnit//MethodDeclarator/FormalParameters
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
获取到参数列表节点后 , 我们查看该节点的属性 , 找出参数个数的属性 , 观察可以发现是ParameterCount属性 。
到现在为止 , 抽象语法树已经分析完 , 我们知道这么找出代码中参数列表大于等于5个的方法了 。
4.2.3.p3c-pmd项目编写自定义代码规则打开阿里p3c-pmd工程 , 开始编写我们的自定义规则 。
阿里已经写了很多规则 , 我们现在要编写的规则属于面向对象范畴 , 可以把规则写到opp包下 , 新建一个规则类MethodParameterCountRule , 继承自AbstractAliRule , 重写 visit方法:
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
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文件中
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
<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中是英文提示 , 这里就先不演示了
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
<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文件中
推荐一个 Spring Boot 基础教程及实战示例:
https://github.com/javastacks/spring-boot-best-practice
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
<?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>编写单元测试
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
运行单元测试 , 因为样例代码中methodB不符合规范 , 但是我们预期问题个数写的是0 , 所以单元测试会不通过:
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
4.3.配置插件4.3.1.p3c-pmd打包安装到本地maven仓库先把用不到的插件maven-javadoc-plugin和maven-gpg-plugin注释掉 , 然后运行mvn命令:
mvn -DskipTests=true clean install4.3.2.idea-plugin项目打包插件idea-plugin项目基于gradle构建 , 配置根目录下build.gradle , 让构建使用本地私有maven仓库构建
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
然后运行开始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
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
4.3.3.IDEA中使用编码规约插件【同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。】安装完插件重启IDEA , 用之前的代码测试下插件是否生效 。
右键点击“编码规约扫描”
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
结果:
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
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>如果存在不符合规范代码打包将失败:
同事写的代码很垃圾 别再写垃圾代码了:试试阿里巴巴 Java 开发插件,打造你的团队专属风格。。。

文章插图
关于maven pmd插件更详细介绍参考官网
6.总结本文篇幅确实有点长 , 看懂需要有点耐心 。不过其实也挺简单 , 关键点就是分析抽象语法树 , 找出问题代码节点 , 剩下的工作就很简单了 。
PMD也有局限性 , 比如只能校验java源文件 , 对于XML等配置规约就没辙了 。还有最最重要的 , 代码逻辑等关键性问题是没法校验的 , 也没法做 。PMD只是一定程度上规范了我们的代码 , 要写出优雅的代码 , 还得多思考多实践呐 。
来源:blog.csdn.net/u014513883/article/details/79186893
近期热文推荐:
1.1,000+ 道 Java面试题及答案整理(2022最新版)
2.劲爆!Java 协程要来了 。。。
3.Spring Boot 2.x 教程 , 太全了!
4.别再写满屏的爆爆爆炸类了 , 试试装饰器模式 , 这才是优雅的方式!!
5.《Java开发手册(嵩山版)》最新发布 , 速速下载!
觉得不错 , 别忘了随手点赞+转发哦!