Apex Code Style Best Practices

7 min read

This article is based on the PMD documentation article. See the original article on the PMD site: PMD: best practices.

Best practices which enforce a specific coding style.

AssignmentInOperand #

Avoid assignments in operands; this can make code more complicated and harder to read. This is sometime indicative of the bug where the assignment operator ‘=’ was used instead of the equality operator ‘==’.

This rule is defined by the following XPath expression://IfStatement[$allowIf = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = “–” or @Image = “++”)]] | //WhileLoop[$allowWhile = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = “–” or @Image = “++”)]] | //DoLoop[$allowWhile = false()]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = “–” or @Image = “++”)]] | //ForLoop[$allowFor = false()]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = “–” or @Image = “++”)]] | //ConditionalExpression[$allowTernary = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = “–” or @Image = “++”)]] | //ConditionalExpression[$allowTernaryResults = false()]/child::node()[position() = 2 or position() = 3]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = “–” or @Image = “++”)]]

Example #

var x = 2; // Bad if ((x = getX()) == 3) { alert(‘3!’); } function getX() { return 3; }

Properties #

NameDefault ValueDescriptionMultivalued
allowIffalseAllow assignment within the conditional expression of an if statementno
allowForfalseAllow assignment within the conditional expression of a for statementno
allowWhilefalseAllow assignment within the conditional expression of a while statementno
allowTernaryfalseAllow assignment within the conditional expression of a ternary operatorno
allowTernaryResultsfalseAllow assignment within the result expressions of a ternary operatorno
allowIncrementDecrementfalseAllow increment or decrement operators within the conditional expression of an if, for, or while statementno

AvoidWithStatement #

Avoid using with – it’s bad news

This rule is defined by the following XPath expression://WithStatement

Example #

with (object) { property = 3; // Might be on object, might be on window: who knows. }

ClassNamingConventions #

Class names should always begin with an upper case character.

This rule is defined by the following Java class:

net.sourceforge.pmd.lang.apex.rule.codestyle.ClassNamingConventionsRule

Example #

public class Foo {}

Properties #

NameDefault ValueDescription
cc_categories[Style]Code Climate Categories
cc_remediation_points_multiplier1Code Climate Remediation Points multiplier
cc_block_highlightingfalseCode Climate Block Highlighting

ConsistentReturn #

ECMAScript does provide for return types on functions, and therefore there is no solid rule as to their usage. However, when a function does use returns they should all have a value, or all with no value. Mixed return usage is likely a bug, or at best poor style.

This rule is defined by the following Java class: 

net.sourceforge.pmd.lang.ecmascript.rule.bestpractices.ConsistentReturnRule

Example #

// Ok function foo() { if (condition1) { return true; } return false; } // Bad function bar() { if (condition1) { return; } return false; }

Parameters #

NameDefault ValueDescriptionMultivalued
rhinoLanguageVersionES6Specifies the Rhino Language Version to use for parsing. Defaults to ES6.no
recordingLocalJsDocCommentstrueSpecifies that JsDoc comments are produced in the AST.no
recordingCommentstrueSpecifies that comments are produced in the AST.no

ForLoopsMustUseBraces #

Avoid using ‘for’ statements without using surrounding braces. If the code formatting or indentation is lost then it becomes difficult to separate the code being controlled from the rest.

//ForLoopStatement/BlockStatement[@CurlyBrace='false']
|
//ForEachStatement/BlockStatement[@CurlyBrace='false']

Example #

for (int i = 0; i < 42; i++) // not recommended foo(); for (int i = 0; i < 42; i++) { // preferred approach foo(); }

Properties #

NameDefault ValueDescription
cc_categories[Style]Code Climate Categories
cc_remediation_points_multiplier1Code Climate Remediation Points multiplier
cc_block_highlightingfalseCode Climate Block Highlighting

GlobalVariable #

This rule helps to avoid using accidently global variables by simply missing the “var” declaration. Global variables can lead to side-effects that are hard to debug.

This rule is defined by the following XPath expression://Assignment[Name/@GlobalName = true()]

Example #

function(arg) { notDeclaredVariable = 1; // this will create a global variable and trigger the rule var someVar = 1; // this is a local variable, that’s ok window.otherGlobal = 2; // this will not trigger the rule, although it is a global variable. }

IfElseStmtsMustUseBraces #

Avoid using if..else statements without using surrounding braces. If the code formatting or indentation is lost then it becomes difficult to separate the code being controlled from the rest.

//IfBlockStatement/BlockStatement[@CurlyBrace='false'][count(child::*) > 0]
|
//IfElseBlockStatement/BlockStatement[@CurlyBrace='false'][count(child::*) > 0]

Example #

// this is OK if (foo) x++; // but this is not if (foo) x = x+1; else x = x-1;

Properties #

NameDefault ValueDescription
cc_categories[Style]Code Climate Categories
cc_remediation_points_multiplier1Code Climate Remediation Points multiplier
cc_block_highlightingfalseCode Climate Block Highlighting

IfStmtsMustUseBraces #

Avoid using if statements without using braces to surround the code block. If the code formatting or indentation is lost then it becomes difficult to separate the code being controlled from the rest.

//IfBlockStatement/BlockStatement[@CurlyBrace='false']

Example #

if (foo) // not recommended x++; if (foo) { // preferred approach x++; }

Properties #

NameDefault ValueDescription
cc_categories[Style]Code Climate Categories
cc_remediation_points_multiplier1Code Climate Remediation Points multiplier
cc_block_highlightingfalseCode Climate Block Highlighting

MethodNamingConventions #

Method names should always begin with a lower case character, and should not contain underscores.

This rule is defined by the following Java class:

net.sourceforge.pmd.lang.apex.rule.codestyle.MethodNamingConventionsRule

Example #

public class Foo { public void fooStuff() { } }

Properties #

NameDefault ValueDescription
cc_categories[Style]Code Climate Categories
cc_remediation_points_multiplier1Code Climate Remediation Points multiplier
cc_block_highlightingfalseCode Climate Block Highlighting

NoElseReturn #

The else block in a if-else-construct is unnecessary if the if block contains a return. Then the content of the else block can be put outside.

See also: http://eslint.org/docs/rules/no-else-return

This rule is defined by the following XPath expression://IfStatement[@Else=true()][Scope[1]/ReturnStatement]

Example #

// Bad: if (x) { return y; } else { return z; } // Good: if (x) { return y; } return z;

UnnecessaryBlock #

An unnecessary Block is present. Such Blocks are often used in other languages to introduce a new variable scope. Blocks do not behave like this in ECMAScipt, and using them can be misleading. Considering removing this unnecessary Block.

This rule is defined by the following XPath expression://Block[not(parent::FunctionNode or parent::IfStatement or parent::ForLoop or parent::ForInLoop or parent::WhileLoop or parent::DoLoop or parent::TryStatement or parent::CatchClause)] | //Scope[not(parent::FunctionNode or parent::IfStatement or parent::ForLoop or parent::ForInLoop or parent::WhileLoop or parent::DoLoop or parent::TryStatement or parent::CatchClause)]

Example #

if (foo) { // Ok } if (bar) { { // Bad } }

UnnecessaryParentheses #

Unnecessary parentheses should be removed.

This rule is defined by the following XPath expression://ParenthesizedExpression/ParenthesizedExpression

Example #

var x = 1; // Ok var y = (1 + 1); // Ok var z = ((1 + 1)); // Bad

UnreachableCode #

A ‘return’, ‘break’, ‘continue’, or ‘throw’ statement should be the last in a block. Statements after these will never execute. This is a bug, or extremely poor style.

This rule is defined by the following XPath expression://ReturnStatement[following-sibling::node()] | //ContinueStatement[following-sibling::node()] | //BreakStatement[following-sibling::node()] | //ThrowStatement[following-sibling::node()]

Example #

// Ok function foo() { return 1; } // Bad function bar() { var x = 1; return x; x = 2; }

UseBaseWithParseInt #

This rule checks for usages of parseInt. While the second parameter is optional and usually defaults to 10 (base/radix is 10 for a decimal number), different implementations may behave differently. It also improves readability, if the base is given.

See also: parseInt()

This rule is defined by the following XPath expression://FunctionCall/Name[ @Image = ‘parseInt’ and count(../*) < 3 ]

Example #

parseInt(“010”); // unclear, could be interpreted as 10 or 7 (with a base of 7) parseInt(“10”, 10); // good

VariableNamingConventions #

A variable naming conventions rule – customize this to your liking. Currently, it checks for final variables that should be fully capitalized and non-final variables that should not include underscores.

This rule is defined by the following Java class:

net.sourceforge.pmd.lang.apex.rule.codestyle.VariableNamingConventionsRule

Example #

public class Foo { public static final Integer MY_NUM = 0; public String myTest = ”; DataModule dmTest = new DataModule(); }

Properties #

NameDefault ValueDescription
parameterSuffix[]Method parameter variable suffixes
parameterPrefix[]Method parameter variable prefixes
localSuffix[]Local variable suffixes
localPrefix[]Local variable prefixes
memberSuffix[]Member variable suffixes
memberPrefix[]Member variable prefixes
staticSuffix[]Static variable suffixes
staticPrefix[]Static variable prefixes
checkParameterstrueCheck constructor and method parameter variables
checkLocalstrueCheck local variables
cc_categories[Style]Code Climate Categories
cc_remediation_points_multiplier1Code Climate Remediation Points multiplier
cc_block_highlightingfalseCode Climate Block Highlighting
checkMemberstrueCheck member variables

WhileLoopsMustUseBraces #

Avoid using ‘while’ statements without using braces to surround the code block. If the code formatting or indentation is lost then it becomes difficult to separate the code being controlled from the rest.

//WhileLoopStatement/BlockStatement[@CurlyBrace='false']

Example #

while (true) // not recommended x++; while (true) { // preferred approach x++; }

Properties #

NameDefault ValueDescription
cc_categories[Style]Code Climate Categories
cc_remediation_points_multiplier1Code Climate Remediation Points multiplier
cc_block_highlightingfalseCode Climate Block Highlighting
Updated on March 21, 2025