ruleDescriptionurlkpiexample
CyclomaticComplexityThe complexity of methods directly affects maintenance costs and readability. Concentrating too much decisional logic_x000D_
in a single method makes its behaviour hard to read and change._x000D_
_x000D_
Cyclomatic complexity assesses the complexity of a method by counting the number of decision points in a method,_x000D_
plus one for the method entry. Decision points are places where the control flow jumps to another place in the_x000D_
program. As such, they include all control flow statements, such as 'if', 'while', 'for', and 'case'._x000D_
_x000D_
Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote_x000D_
high complexity, and 11+ is very high complexity. By default, this rule reports methods with a complexity >= 10._x000D_
Additionally, classes with many methods of moderate complexity get reported as well once the total of their_x000D_
methods' complexities reaches 40, even if none of the methods was directly reported._x000D_
_x000D_
Reported methods should be broken down into several smaller methods. Reported classes should probably be broken down_x000D_
into subcomponents.
https://pmd.github.io/latest/pmd_rules_apex_design.html#cyclomaticcomplexityMaintainabilitypublic class Complicated {
public void example() { // This method has a cyclomatic complexity of 12
int x = 0, y = 1, z = 2, t = 2;
boolean a = false, b = true, c = false, d = true;
if (a && b || b && d) {
if (y == z) {
x = 2;
} else if (y == t && !d) {
x = 2;
} else {
x = 2;
}
} else if (c && d) {
while (z < y) {
x = 2;
}
} else {
for (int n = 0; n < t; n++) {
x = 2;
}
}
}
}
CognitiveComplexityMethods that are highly complex are difficult to read and more costly to maintain. If you include too much decisional
logic 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 contains
a break in the control flow is more complex, whereas the use of language shorthands doesn't increase the level of
complexity. Nested control flows can make a method more difficult to understand, with each additional nesting of the
control 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 less
complex components.
https://pmd.github.io/latest/pmd_rules_apex_design.html#cognitivecomplexityMaintainabilitypublic class Foo {
// Has a cognitive complexity of 0
public void createAccount() {
Account account = new Account(Name = 'PMD');
insert account;
}
// Has a cognitive complexity of 1
public Boolean setPhoneNumberIfNotExisting(Account a, String phone) {
if (a.Phone == null) { // +1
a.Phone = phone;
update a;
return true;
}
return false;
}
// Has a cognitive complexity of 5
public void updateContacts(List contacts) {
List contactsToUpdate = new List();
for (Contact contact : contacts) { // +1
if (contact.Department == 'Finance') { // +2
contact.Title = 'Finance Specialist';
contactsToUpdate.add(contact);
} else if (contact.Department == 'Sales') { // +2
contact.Title = 'Sales Specialist';
contactsToUpdate.add(contact);
}
}
update contactsToUpdate;
}
}
StdCyclomaticComplexityComplexity directly affects maintenance costs is determined by the number of decision points in a method_x000D_
plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls._x000D_
Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote_x000D_
high complexity, and 11+ is very high complexity.
https://pmd.github.io/latest/pmd_rules_apex_design.html#stdcyclomaticcomplexityMaintainability_x000D_
// This has a Cyclomatic Complexity = 12_x000D_
public class Foo {_x000D_
1 public void example() {_x000D_
2 if (a == b || (c == d && e == f)) {_x000D_
3 if (a1 == b1) {_x000D_
fiddle();_x000D_
4 } else if a2 == b2) {_x000D_
fiddle();_x000D_
} else {_x000D_
fiddle();_x000D_
}_x000D_
5 } else if (c == d) {_x000D_
6 while (c == d) {_x000D_
fiddle();_x000D_
}_x000D_
7 } else if (e == f) {_x000D_
8 for (int n = 0; n < h; n++) {_x000D_
fiddle();_x000D_
}_x000D_
} else {_x000D_
switch (z) {_x000D_
9 case 1:_x000D_
fiddle();_x000D_
break;_x000D_
10 case 2:_x000D_
fiddle();_x000D_
break;_x000D_
11 case 3:_x000D_
fiddle();_x000D_
break;_x000D_
12 default:_x000D_
fiddle();_x000D_
break;_x000D_
}_x000D_
}_x000D_
}_x000D_
AvoidHardcodingIdWhen deploying Apex code between sandbox and production environments, or installing Force.com AppExchange packages,
it is essential to avoid hardcoding IDs in the Apex code. By doing so, if the record IDs change between environments,
the logic can dynamically identify the proper data to operate against and not fail.
https://pmd.github.io/latest/pmd_rules_apex_errorprone.html#avoidhardcodingidMaintainability
EmptyTryOrFinallyBlockAvoid empty try or finally blocks - what's the point?https://pmd.github.io/latest/pmd_rules_apex_errorprone.html#emptytryorfinallyblockMaintainability
OverrideBothEqualsAndHashcodeOverride both `public Boolean equals(Object obj)`, and `public Integer hashCode()`, or override neither._x000D_
Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly_x000D_
delegating to your superclass._x000D_
_x000D_
This is especially important when [Using Custom Types in Map Keys and Sets](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_collections_maps_keys_userdefined.htm).
https://pmd.github.io/latest/pmd_rules_apex_errorprone.html#overridebothequalsandhashcodeMaintainability
OperationWithLimitsInLoopDatabase class methods, DML operations, SOQL queries, or SOSL queries within loops can cause governor limit exceptions. Instead, try to batch up the data into a list and invoke the operation once on that list of data outside the loop.https://pmd.github.io/latest/pmd_rules_apex_performance.html#operationwithlimitsinloopMaintainability_x000D_
public class Something {_x000D_
public void databaseMethodInsideOfLoop(List accounts) {_x000D_
for (Account a : accounts) {_x000D_
Database.insert(a);_x000D_
}_x000D_
}_x000D_
public void dmlInsideOfLoop() {_x000D_
for (Integer i = 0; i < 151; i++) {_x000D_
Account account;_x000D_
// ..._x000D_
insert account;_x000D_
}_x000D_
}_x000D_
public void soqlInsideOfLoop() {_x000D_
for (Integer i = 0; i < 10; i++) {_x000D_
List accounts = [SELECT Id FROM Account];_x000D_
}_x000D_
}_x000D_
public void soslInsideOfLoop() {_x000D_
for (Integer i = 0; i < 10; i++) {_x000D_
List> searchList = [FIND 'map*' IN ALL FIELDS RETURNING Account (Id, Name), Contact, Opportunity, Lead];_x000D_
}_x000D_
}_x000D_
}_x000D_
ApexSharingViolationsDetect classes declared without explicit sharing mode if DML methods are used. This_x000D_
forces the developer to take access restrictions into account before modifying objects.
https://pmd.github.io/latest/pmd_rules_apex_security.html#apexsharingviolationsMaintainability