rule | Description | url | kpi | example |
---|---|---|---|---|
CyclomaticComplexity | The 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#cyclomaticcomplexity | Maintainability | public 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; } } } } |
CognitiveComplexity | Methods 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#cognitivecomplexity | Maintainability | public 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 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; } } |
StdCyclomaticComplexity | Complexity 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#stdcyclomaticcomplexity | Maintainability | _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_ |
AvoidHardcodingId | When 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#avoidhardcodingid | Maintainability | |
EmptyTryOrFinallyBlock | Avoid empty try or finally blocks - what's the point? | https://pmd.github.io/latest/pmd_rules_apex_errorprone.html#emptytryorfinallyblock | Maintainability | |
OverrideBothEqualsAndHashcode | Override 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#overridebothequalsandhashcode | Maintainability | |
OperationWithLimitsInLoop | Database 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#operationwithlimitsinloop | Maintainability | _x000D_ public class Something {_x000D_ public void databaseMethodInsideOfLoop(List 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 }_x000D_ }_x000D_ public void soslInsideOfLoop() {_x000D_ for (Integer i = 0; i < 10; i++) {_x000D_ List
}_x000D_ }_x000D_ }_x000D_ |
ApexSharingViolations | Detect 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#apexsharingviolations | Maintainability |