PMD is very well known source code analyzer for Java, android and many more languages. Good news for us (Salesforce developers) is , that it supports now Apex. You might be thinking how can we make PMD as part of our daily life ?
There are multiple ways
- We can run static code analysis standalone
- It can be part of ANT build to generate error reports
- Jenkins can use it to generate nice report around code quality
- Eclipse can use it as a plugin to generate report
In this blog post, we will discuss option 1, that is running it as a standalone application to generate code quality report.
First Step is to download jar file of latest PMD distribution from here.
Next step is to define some rules for your code base. Sample rules can be seen here. We can also create our own rule as per need. For this blog post, I would be using below rules.
Apex Rules.xml
<?xml version="1.0"?> <ruleset name="Apex Rules" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd"> <rule name="AvoidDeeplyNestedIfStmts" message="Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain." class="net.sourceforge.pmd.lang.apex.rule.complexity.AvoidDeeplyNestedIfStmtsRule"> <description> Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain. </description> <priority>3</priority> <example> <![CDATA[ public class Foo { public void bar(Integer x, Integer y, Integer z) { if (x>y) { if (y>z) { if (z==x) { // !! too deep } } } } } ]]> </example> </rule> <rule name="ExcessiveParameterList" message="Methods with numerous parameters are a challenge to maintain, especially if most of them share the same datatype. These situations usually denote the need for new objects to wrap the numerous parameters." class="net.sourceforge.pmd.lang.apex.rule.complexity.ExcessiveParameterListRule"> <description> Methods with numerous parameters are a challenge to maintain, especially if most of them share the same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. </description> <priority>3</priority> <example> <![CDATA[ // too many arguments liable to be mixed up public void addPerson(int birthYear, int birthMonth, int birthDate, int height, int weight, int ssn) { ... } // preferred approach public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) { ... } ]]> </example> </rule> <rule name="ExcessiveClassLength" message="Excessive class file lengths are usually indications that the class may be burdened with excessive responsibilities that could be provided by external classes or functions. In breaking these methods apart the code becomes more managable and ripe for reuse." class="net.sourceforge.pmd.lang.apex.rule.complexity.ExcessiveClassLengthRule"> <description> Excessive class file lengths are usually indications that the class may be burdened with excessive responsibilities that could be provided by external classes or functions. In breaking these methods apart the code becomes more managable and ripe for reuse. </description> <priority>3</priority> <example> <![CDATA[ public class Foo { public void bar(Integer x, Integer y, Integer z) { if (x>y) { if (y>z) { if (z==x) { // !! too deep } } } } } ]]> </example> </rule> <rule name="NcssMethodCount" message="This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one." class="net.sourceforge.pmd.lang.apex.rule.complexity.NcssMethodCountRule"> <description> This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. </description> <priority>3</priority> <example> <![CDATA[ public class Foo extends Bar { //this method only has 1 NCSS lines public Integer methd() { super.methd(); return 1; } } ]]> </example> </rule> </ruleset>
In above sample rule file, if we observe carefully, each rule is represented by rule tag. we can give it any name and then message to be displayed in report. class represents respective rule written in Java class by PMD and this information would be available here.
priority can set level of violations and this would differ as per your project. We can categorize level of violations for each rule and it helps us in reporting code quality of developer team.
Final step is to run below command from shell / command prompt. This documentation will help to understand all parameters needed to run PMD from command prompt.
pmd -d "path of folder where all apex files exists" -f html -R "path of rule file in our case above file ApexRules.xml" -reportfile "path of report to be generated"
Following image shows sample command run
Below is sample code quality report generated
Youtube video
Leave a Reply