Since: PMD 7.15.0
Priority: Medium High (2)
Boolean parameters in a system’s API can make method calls difficult to understand andmaintain. They often indicate that a method is doing more than one thing andcould benefit from being split into separate methods with more descriptivenames.
This rule flags any boolean parameters found in public or global methods,encouraging developers to use more expressive alternatives such as enums,separate methods, or configuration objects.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.AvoidBooleanMethodParametersRule
Example(s):
// Violates the rule: Uses a Boolean parameterpublicclassMyClass{publicstaticvoiddoSomething(BooleanisSomething){if(isSomething==true){// Do something}else{// Do something else, or maybe do nothing if isSomething is null?}}}// Compliant code: Two separate methodspublicclassMyClass{publicstaticvoiddoSomething(){// Do something}publicstaticvoiddoSomethingElse(){// Do something else}}publicvoidsetFlag(Booleanstrict){...}// violation// compliantpublicvoidenableStrictChecking(){...}publicvoiddisableStrictChecking(){...}Use this rule by referencing it:
<ruleref="category/apex/design.xml/AvoidBooleanMethodParameters"/>Since: PMD 5.5.0
Priority: Medium (3)
Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.AvoidDeeplyNestedIfStmtsRule
Example(s):
publicclassFoo{publicvoidbar(Integerx,Integery,Integerz){if(x>y){if(y>z){if(z==x){// !! too deep}}}}}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| problemDepth | 3 | The if statement depth reporting threshold |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/design.xml/AvoidDeeplyNestedIfStmts"/>Use this rule and customize it:
<ruleref="category/apex/design.xml/AvoidDeeplyNestedIfStmts"><properties><propertyname="problemDepth"value="3"/></properties></rule>Since: PMD 6.22.0
Priority: Medium (3)
Methods that are highly complex are difficult to read and more costly to maintain. If you include too much decisionallogic within a single method, you make its behavior hard to understand and more difficult to modify.
Cognitive complexity is a measure of how difficult it is for humans to read and understand a method. Code that containsa break in the control flow is more complex, whereas the use of language shorthands doesn’t increase the level ofcomplexity. Nested control flows can make a method more difficult to understand, with each additional nesting of thecontrol flow leading to an increase in cognitive complexity.
Information about Cognitive complexity can be found in the original paper here:https://www.sonarsource.com/docs/CognitiveComplexity.pdf
By default, this rule reports methods with a complexity of 15 or more. Reported methods should be broken down into lesscomplex components.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.CognitiveComplexityRule
Example(s):
publicclassFoo{// Has a cognitive complexity of 0publicvoidcreateAccount(){Accountaccount=newAccount(Name='PMD');insertaccount;}// Has a cognitive complexity of 1publicBooleansetPhoneNumberIfNotExisting(Accounta,Stringphone){if(a.Phone==null){// +1a.Phone=phone;updatea;returntrue;}returnfalse;}// Has a cognitive complexity of 4publicvoidupdateContacts(List<Contact>contacts){List<Contact>contactsToUpdate=newList<Contact>();for(Contactcontact:contacts){// +1if(contact.Department=='Finance'){// +2 (nesting = 1)contact.Title='FinanceSpecialist';contactsToUpdate.add(contact);}elseif(contact.Department=='Sales'){// +1contact.Title='SalesSpecialist';contactsToUpdate.add(contact);}}updatecontactsToUpdate;}}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| classReportLevel | 50 | Total class cognitive complexity reporting threshold |
| methodReportLevel | 15 | Cognitive complexity reporting threshold |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/design.xml/CognitiveComplexity"/>Use this rule and customize it:
<ruleref="category/apex/design.xml/CognitiveComplexity"><properties><propertyname="classReportLevel"value="50"/><propertyname="methodReportLevel"value="15"/></properties></rule>Since: PMD 6.0.0
Priority: Medium (3)
The complexity of methods directly affects maintenance costs and readability. Concentrating too much decisional logicin a single method makes its behaviour hard to read and change.
Cyclomatic complexity assesses the complexity of a method by counting the number of decision points in a method,plus one for the method entry. Decision points are places where the control flow jumps to another place in theprogram. As such, they include all control flow statements, such as ‘if’, ‘while’, ‘for’, and ‘case’.
Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denotehigh complexity, and 11+ is very high complexity. By default, this rule reports methods with a complexity >= 10.Additionally, classes with many methods of moderate complexity get reported as well once the total of theirmethods’ complexities reaches 40, even if none of the methods was directly reported.
Reported methods should be broken down into several smaller methods. Reported classes should probably be broken downinto subcomponents.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.CyclomaticComplexityRule
Example(s):
publicclassComplicated{publicvoidexample(){// This method has a cyclomatic complexity of 12intx=0,y=1,z=2,t=2;booleana=false,b=true,c=false,d=true;if(a&&b||b&&d){if(y==z){x=2;}elseif(y==t&&!d){x=2;}else{x=2;}}elseif(c&&d){while(z<y){x=2;}}else{for(intn=0;n<t;n++){x=2;}}}}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| classReportLevel | 40 | Total class complexity reporting threshold |
| methodReportLevel | 10 | Cyclomatic complexity reporting threshold |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/design.xml/CyclomaticComplexity"/>Use this rule and customize it:
<ruleref="category/apex/design.xml/CyclomaticComplexity"><properties><propertyname="classReportLevel"value="40"/><propertyname="methodReportLevel"value="10"/></properties></rule>Deprecated
Since: PMD 5.5.0
Priority: Medium (3)
Excessive class file lengths are usually indications that the class may be burdened with excessiveresponsibilities that could be provided by external classes or functions. In breaking these methodsapart the code becomes more manageable and ripe for reuse.
Deprecated: This rule is deprecated since PMD 7.19.0 and will be removed with PMD 8.0.0. UseNcssCount to find big classes.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.ExcessiveClassLengthRule
Example(s):
publicclassFoo{publicvoidbar1(){// 1000 lines of code}publicvoidbar2(){// 1000 lines of code}publicvoidbar3(){// 1000 lines of code}publicvoidbarN(){// 1000 lines of code}}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| minimum | 1000 | Threshold at or above which a node is reported |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/design.xml/ExcessiveClassLength"/>Use this rule and customize it:
<ruleref="category/apex/design.xml/ExcessiveClassLength"><properties><propertyname="minimum"value="1000"/></properties></rule>Since: PMD 5.5.0
Priority: Medium (3)
Methods with numerous parameters are a challenge to maintain, especially if most of them share thesame datatype. These situations usually denote the need for new objects to wrap the numerous parameters.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.ExcessiveParameterListRule
Example(s):
// too many arguments liable to be mixed uppublicvoidaddPerson(IntegerbirthYear,IntegerbirthMonth,IntegerbirthDate,Integerheight,Integerweight,Integerssn){// ...}// preferred approachpublicvoidaddPerson(Datebirthdate,BodyMeasurementsmeasurements,intssn){// ...}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| minimum | 4 | Threshold at or above which a node is reported |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/design.xml/ExcessiveParameterList"/>Use this rule and customize it:
<ruleref="category/apex/design.xml/ExcessiveParameterList"><properties><propertyname="minimum"value="4"/></properties></rule>Since: PMD 5.5.0
Priority: Medium (3)
Classes with large numbers of public methods, attributes, and properties require disproportionate testing effortssince combinatorial side effects grow rapidly and increase risk. Refactoring these classes intosmaller ones not only increases testability and reliability but also allows new variations to bedeveloped easily.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.ExcessivePublicCountRule
Example(s):
publicclassFoo{publicStringvalue;publicBarsomething;publicVariablevar;// [... more more public attributes ...]publicvoiddoWork(){}publicvoiddoMoreWork(){}publicvoiddoWorkAgain(){}// [... more more public methods ...]publicStringproperty1{get;set;}// [... more more public properties ...]}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| minimum | 20 | Threshold at or above which a node is reported |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/design.xml/ExcessivePublicCount"/>Use this rule and customize it:
<ruleref="category/apex/design.xml/ExcessivePublicCount"><properties><propertyname="minimum"value="20"/></properties></rule>Deprecated
Since: PMD 5.5.0
Priority: Medium (3)
This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of linesof code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm,lines of code that are split are counted as one.
Deprecated: This rule is deprecated since PMD 7.19.0 and will be removed with PMD 8.0.0. UseNcssCount instead.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.NcssConstructorCountRule
Example(s):
publicclassFooextendsBar{//this constructor only has 1 NCSS linespublicFoo(){super();super.foo();}}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| minimum | 20 | Threshold at or above which a node is reported |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/design.xml/NcssConstructorCount"/>Use this rule and customize it:
<ruleref="category/apex/design.xml/NcssConstructorCount"><properties><propertyname="minimum"value="20"/></properties></rule>Since: PMD 7.19.0
Priority: Medium (3)
This rule uses the NCSS (Non-Commenting Source Statements) metric to determine the number of linesof code in a class, method or constructor. NCSS ignores comments, blank lines, and only counts actualstatements. For more details on the calculation, see the documentationNCSS.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.NcssCountRule
Example(s):
classFoo{// +1, total Ncss = 12publicvoidbigMethod()// +1{intx=0,y=2;// +1booleana=false,b=true;// +1if(a||b){// +1try{// +1do{// +1x+=2;// +1}while(x<12);System.exit(0);// +1}catch(IOExceptionioe){// +1thrownewPatheticFailException(ioe);// +1}}else{System.out.println('false');// +1}}}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| methodReportLevel | 40 | NCSS reporting threshold for methods |
| classReportLevel | 500 | NCSS reporting threshold for classes |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/design.xml/NcssCount"/>Use this rule and customize it:
<ruleref="category/apex/design.xml/NcssCount"><properties><propertyname="methodReportLevel"value="40"/><propertyname="classReportLevel"value="500"/></properties></rule>Deprecated
Since: PMD 5.5.0
Priority: Medium (3)
This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of linesof 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.
Deprecated: This rule is deprecated since PMD 7.19.0 and will be removed with PMD 8.0.0. UseNcssCount instead.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.NcssMethodCountRule
Example(s):
publicclassFooextendsBar{//this method only has 1 NCSS linespublicIntegermethod(){super.method();return1;}}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| minimum | 40 | Threshold at or above which a node is reported |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/design.xml/NcssMethodCount"/>Use this rule and customize it:
<ruleref="category/apex/design.xml/NcssMethodCount"><properties><propertyname="minimum"value="40"/></properties></rule>Deprecated
Since: PMD 5.5.0
Priority: Medium (3)
This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of linesof code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm,lines of code that are split are counted as one.
Deprecated: This rule is deprecated since PMD 7.19.0 and will be removed with PMD 8.0.0. UseNcssCount instead.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.NcssTypeCountRule
Example(s):
//this class only has 6 NCSS linespublicclassFooextendsBar{publicFoo(){super();super.foo();}}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| minimum | 500 | Threshold at or above which a node is reported |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/design.xml/NcssTypeCount"/>Use this rule and customize it:
<ruleref="category/apex/design.xml/NcssTypeCount"><properties><propertyname="minimum"value="500"/></properties></rule>Since: PMD 5.5.0
Priority: Medium (3)
Complexity directly affects maintenance costs is determined by the number of decision points in a methodplus one for the method entry. The decision points include ‘if’, ‘while’, ‘for’, and ‘case labels’ calls.Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denotehigh complexity, and 11+ is very high complexity.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.StdCyclomaticComplexityRule
Example(s):
// This has a Cyclomatic Complexity = 12publicclassFoo{1publicvoidexample(){2if(a==b||(c==d&&e==f)){3if(a1==b1){fiddle();4}elseifa2==b2){fiddle();}else{fiddle();}5}elseif(c==d){6while(c==d){fiddle();}7}elseif(e==f){8for(intn=0;n<h;n++){fiddle();}}else{switch(z){9case1:fiddle();break;10case2:fiddle();break;11case3:fiddle();break;12default:fiddle();break;}}}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| reportLevel | 10 | Cyclomatic Complexity reporting threshold |
| showClassesComplexity | true | Add class average violations to the report |
| showMethodsComplexity | true | Add method average violations to the report |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/design.xml/StdCyclomaticComplexity"/>Use this rule and customize it:
<ruleref="category/apex/design.xml/StdCyclomaticComplexity"><properties><propertyname="reportLevel"value="10"/><propertyname="showClassesComplexity"value="true"/><propertyname="showMethodsComplexity"value="true"/></properties></rule>Since: PMD 5.5.0
Priority: Medium (3)
Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields,possibly through grouping related fields in new objects. For example, a class with individualcity/state/zip fields could park them within a single Address field.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.TooManyFieldsRule
Example(s):
publicclassPerson{// too many separate fieldsIntegerbirthYear;IntegerbirthMonth;IntegerbirthDate;Doubleheight;Doubleweight;}publicclassPerson{// this is more manageableDatebirthDate;BodyMeasurementsmeasurements;}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| maxfields | 15 | Max allowable fields |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/design.xml/TooManyFields"/>Use this rule and customize it:
<ruleref="category/apex/design.xml/TooManyFields"><properties><propertyname="maxfields"value="15"/></properties></rule>Since: PMD 7.0.0
Priority: Medium (3)
Avoid having unused methods since they make understanding and maintaining code harder.
This rule finds not only unused private methods, but public methods as well, as long asthe class itself is not entirely unused. A class is considered used, if it contains atleast one other method/variable declaration that is used, as shown in thetest project file Foo.cls.
ApexLink is used to make this possible and this needsadditional configuration. The environment variablePMD_APEX_ROOT_DIRECTORY needs to be set prior to executingPMD. With this variable the root directory of the Salesforce metadata, wheresfdx-project.json resides, isspecified. ApexLink can then load all the classes in the project and figure out, whether a method is used or not.
For an accurate analysis it is important that thePMD_APEX_ROOT_DIRECTORY contains a complete set of metadata thatmay be referenced from the Apex source code, such as Custom Objects, Visualforce Pages, Flows and Labels. ThePMD_APEX_ROOT_DIRECTORY directory must contain asfdx-project.json, but metadata may be either in theSFDX Source formator the older MDAPI format. ThepackageDirectories entries insfdx-project.json are used to determine whichdirectories to search for metadata, if a.forceignore file is present it will be respected.
If the Apex code references external packages via namespace(s) you should declare these in yoursfdx-project.jsonfile using the ‘plugins’ syntax shown in the example below to avoid errors. Here’s an example of awell-formedsfdx-project.json:
{"packageDirectories":[{"path":"src","default":true}],"namespace":"my_namespace","sfdcLoginUrl":"https://login.salesforce.com","sourceApiVersion":"52.0","plugins":{"dependencies":[{"namespace":"aa"}]}}This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.design.UnusedMethodRule
Example(s):
publicclassTriangle{privateDoubleside1;privateDoubleside2;privateDoubleside3;publicTriangle(Doubleside1,Doubleside2,Doubleside3){this.side1=side1;this.side2=side2;this.side3=side3;}// Method is not invoked so can be removedpublicDoublearea(){return(side1+side2+side3)/2;}}Use this rule by referencing it:
<ruleref="category/apex/design.xml/UnusedMethod"/>