1 简介
在工作中,难免会遇到维护别人代码的情况,所以首先要了解别人写的代码。 如果对方写的代码比较杂乱、臃肿,那么维护成本就会很高。 如果对方写的代码优雅、清晰,维护者就会显得心情愉快。 俗话说“前人种树,后人乘凉;前人埋坑,后人骂娘”。
代码首先是给人看的,然后才是机器看的。 如何编写任何人都可以看到和理解的代码? 答案是制定规范!
每个公司都会有自己的编码标准,但往往因为赶项目进度、偷懒或者个人习惯等原因,再加上缺乏代码审查,最终的代码会写成各种怪异的样子。 原因是有规定,但没有人遵守。 因此,编码标准需要得到执行,并由工具来执行。
本文将通过介绍阿里巴巴的p3c开源项目Java静态代码检查工具PMD,最后编写自定义的编码约定来学习如何规范代码编写。
2.PMD静态扫码 2.1. PMD官方网站
2.2.概述
PMD 是一个用于分析 Java 代码错误的开源工具。 它通过静态分析了解代码错误。 也就是没有运行Java程序就报错。
PMD自带了很多可以直接使用的规则。 这些规则可以用来发现Java源程序中的很多问题,例如:
此外,用户还可以定义自己的规则来检查Java代码是否符合某些编码标准。 例如,您可以编写一条规则,要求 PMD 查找创建 Thread 和 Socket 对象的所有操作。
2.3. 工作准则
PMD 的核心是 JavaCC 解析器生成器。 PMD结合了JavaCC和EBNF(扩展巴科斯-诺尔形式)语法,加上JJTree,将Java源代码解析成抽象语法树(AST,Abstract Syntax Tree)
从根本上来说,Java 源代码只是一些普通的文本。 然而,为了让解析器将这些普通文本识别为有效的 Java 代码,它们必须符合某些结构要求。 这种结构可以用称为 EBNF 的句法元语言来表达,通常称为“语法”。 JavaCC根据语法要求生成一个解析器,这个解析器可以用来解析用Java编程语言编写的程序。
2.4. 规则分类2.5。 编写PMD自定义规则3.阿里巴巴Java开发协议插件p3c3.1.GITHUB地址
3.2.概述
阿里巴巴p3c项目由三部分组成:
3.3. 使用阿里编码协议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,继承于AbstractAliRuleasp简单源码 生成静态,并重写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;
@Override
public Object visit(ASTCompilationUnit node, Object data) {
try {
// 找到所方法节点
List methodNodes = node.findChildNodesWithXPath(METHOD_XPATH);
if (methodNodes != null && methodNodes.size() > 0) {
for (Node methodNode : methodNodes) {
// 找到每个方法的参数列表声明
List 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
<![CDATA[
Negative example:
public void methodB(int a, int b, int c, int d, int e) {
}
]]>
<![CDATA[
Positive example:
public void methodA() {
}
]]>
4.2.5.p3c-pmd项目写入提示信息
前两步用到的提示信息和规则信息需要写入message.xml配置文件中。 message_en.xml中包含英文提示,此处不再演示。
<entry key="java.oop.MethodParameterCountRule.violation.msg">
<entry key="java.oop.MethodParameterCountRule.rule.msg">
4.2.6. 单元测试
编写测试样本,将待测试的源码写入测试目录对应的xml文件中。
推荐看这个Spring Boot基础教程和实战例子来做单元测试:
<?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) {
}
}
]]>
<test-code>
0
<code-ref id="测试样例" />
</test-code>
</test-data>
编写单元测试
运行单元测试,因为示例代码中的methodB不符合规范,但我们期望问题数写为0asp简单源码 生成静态,所以单元测试会失败:
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-pluginp3c-ideabuilddistributions目录下生成Alibaba Java CodingGuidelines-1.0.0.zip文件。 这是我们为了扩展阿里巴巴开发协议而添加的插件。 在IDEA中安装此插件:
设置->插件->从磁盘安装插件
4.3.3. 在IDEA中使用编码约定插件
安装插件后,重启IDEA,使用之前的代码测试插件是否生效。
右键单击“编码协议扫描”
结果:
5.Maven打包添加PMD验证
到目前为止,我们已经能够在开发阶段实时验证我们自己的代码。 最后,我们需要对代码打包添加规范检查,使得部署到生产环境的代码符合规范。 如果不符合规格,包装就会失败。
考虑到大多数项目都是使用maven管理的,可以将自定义的pmd规则集成到maven中,这样就可以使用maven来验证代码规则。
将pmd插件添加到maven项目中,并配置插件在package阶段执行。通常我们的项目都有一个共同的父pom,所以只需将插件添加到父pom中即可。
org.apache.maven.plugins
maven-pmd-plugin
3.8
rulesets/java/ali-comment.xml
rulesets/java/ali-concurrent.xml
rulesets/java/ali-constant.xml
rulesets/java/ali-exception.xml
rulesets/java/ali-flowcontrol.xml
rulesets/java/ali-naming.xml
rulesets/java/ali-oop.xml
rulesets/java/ali-orm.xml
rulesets/java/ali-other.xml
rulesets/java/ali-set.xml
true
1
package
check
com.alibaba.p3c
p3c-pmd
1.3.3
如果有不符合规范的代码,打包会失败:
关于maven pmd插件更详细的介绍可以参考官网
六、总结
这篇文章确实有点长,需要一些耐心才能看懂。 但实际上很简单。 关键是分析抽象语法树,找到问题代码节点。 剩下的工作就非常简单了。
PMD 也有局限性。 例如,它只能验证Java源文件,但不能对XML等配置规范做任何事情。 而且最重要的是,代码逻辑等关键问题无法验证,无法完成。 PMD只是在一定程度上规范了我们的代码。 想要写出优雅的代码,需要我们多思考,多实践。
来源:blog.csdn.net/u014513883/article/details/79186893
2022年粉丝福利 http://download.java1234.com/ 每月送 666 套Java海量资源网站 VIP会员,供大伙一起学Java 如果没过锋哥微信的 加一下锋哥微信备注 VIP 即可开通 点个 在看 喜欢是一种感觉 在看是一种支持 ↘↘↘