什么样的代码叫做一个好的代码,相信每个人都有自己心中的一杆秤,而繁荣的Java社区也给了我们很多优秀的代码异味检测工具,Checkstyle,Findbug,PMD就是广为人知的几个。但是针对不同的问题,其中的异味和优秀实践各有不同,为了能够更好的Review迎合具体问题的代码,就需要我们能够在对问题有了了解之后,实现一些自己独有的代码检查规则,那么,以后我们针对这一问题的Code Review效率就会有明显提升。
[b]PMD的工作原理[/b]
PMD通过JavaCC 解析器把源代码解析为一颗AST(Abstract Syntax Tree),然后通过对这个语法树的特征辨识,从而识别出这份源代码是否有自定义的异味。在PMD的代码包中包含了通过源代码一个生成AST的小工具, 启动该工具,我们就可以查看一个类的AST结构了(在Windows直接运行bin目录下的designer.bat, Unix系统运行./run.sh designer)
[img]http://dl.iteye.com/upload/attachment/0071/1301/f1055d04-7ca7-383c-8a1c-318ff4d318da.png[/img]
[b]编写一个自己的规则[/b]
[b]1、定义规则[/b]
没有任何行为的Enum都是坏味道
[b]2、找出规则在AST中的特征[/b]
AST是一个高度结构化的数据,代码上的变化都会在AST结构上留下痕迹,通过PMD designer可以发现,有行为的Enum和没有行为的Enum之间最大的差别就是在EnumBody这个节点下面没有任何方法声明语句MehodDeclaration的存在。
[b]3、编写代码[/b]
编写PMD的Rule必须引入PMD的包,
新的JavaRule必须继承AbstractJavaRule。
[b]4、配置规则信息[/b]
代码写完之后,需要配置相应的rulesets.xml,该文件主要就是配置PMD运行时执行哪些规则,当触犯规则的时候应该显示什么样的错误信息
[b]PMD的工作原理[/b]
PMD通过JavaCC 解析器把源代码解析为一颗AST(Abstract Syntax Tree),然后通过对这个语法树的特征辨识,从而识别出这份源代码是否有自定义的异味。在PMD的代码包中包含了通过源代码一个生成AST的小工具, 启动该工具,我们就可以查看一个类的AST结构了(在Windows直接运行bin目录下的designer.bat, Unix系统运行./run.sh designer)
[img]http://dl.iteye.com/upload/attachment/0071/1301/f1055d04-7ca7-383c-8a1c-318ff4d318da.png[/img]
[b]编写一个自己的规则[/b]
[b]1、定义规则[/b]
没有任何行为的Enum都是坏味道
[b]2、找出规则在AST中的特征[/b]
AST是一个高度结构化的数据,代码上的变化都会在AST结构上留下痕迹,通过PMD designer可以发现,有行为的Enum和没有行为的Enum之间最大的差别就是在EnumBody这个节点下面没有任何方法声明语句MehodDeclaration的存在。
[b]3、编写代码[/b]
编写PMD的Rule必须引入PMD的包,
<dependency>
<groupId>pmd</groupId>
<artifactId>pmd</artifactId>
<version>${pmd.version}</version>
<scope>compile</scope>
</dependency>
新的JavaRule必须继承AbstractJavaRule。
public class EnumWithoutBehavior extends AbstractJavaRule {
@Override
public Object visit(ASTEnumBody node, Object data) {
if (!hasMethodDeclared(node)) addViolation(data, node);
return data;
}
private boolean hasMethodDeclared(ASTEnumBody node) {
return !node.findChildrenOfType(ASTMethodDeclaration.class).isEmpty();
}
}
[b]4、配置规则信息[/b]
代码写完之后,需要配置相应的rulesets.xml,该文件主要就是配置PMD运行时执行哪些规则,当触犯规则的时候应该显示什么样的错误信息
<?xml version="1.0"?>
<ruleset name="Mars Rover Rules"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>
</description>
<rule name="EnumWithoutBehavior"
message="Enumeration without any behavior"
class="com.thoughtworks.cerberus.marsrover.java.EnumWithoutBehavior">
<description></description>
<priority>3</priority>
<example></example>
</rule>
</ruleset>