Apex Code Quality
Code Style and Formatting
Braces Requirement
Always use braces for all control structures (if, else, for, while, etc.), even for single-line statements.
Good Example:
if (account != null) {
processAccount(account);
}
for (Account acc : accounts) {
processAccount(acc);
}
Bad Example:
if (account != null)
processAccount(account);
for (Account acc : accounts)
processAccount(acc);
This is enforced by the Code Analyzer ruleset: IfStmtsMustUseBraces, ForLoopsMustUseBraces, WhileLoopsMustUseBraces, IfElseStmtsMustUseBraces.
Code Formatting Alignment
- Use Prettier for code formatting (configured in
.prettierrc) - Run Prettier before committing code
- Ensure consistent formatting across the codebase
Code Complexity
Cognitive Complexity Limits
- Method level: Maximum 15
- Class level: Maximum 50
These limits are enforced by the Code Analyzer ruleset. If complexity exceeds these limits, refactor the code.
NCSS Limits (Non-Commenting Source Statements)
- Method level: Maximum 60 lines
- Class level: Maximum 1000 lines
These limits are enforced by the Code Analyzer ruleset (NcssCount rule).
Nesting Depth Limits
- Maximum nesting depth: 4 levels
Deeply nested if/else statements are hard to read and maintain. Use early returns or refactor to reduce nesting.
Example - Too Deep:
if (condition1) {
if (condition2) {
if (condition3) {
if (condition4) {
if (condition5) { // Too deep!
// Code
}
}
}
}
}
Example - Refactored:
if (!condition1) {
return;
}
if (!condition2) {
return;
}
if (!condition3) {
return;
}
// Continue with less nesting
Parameter Count Limits
- Maximum parameters: 5
If a method requires more than 5 parameters, consider:
- Using a parameter object/wrapper class
- Refactoring into multiple methods
- Using a builder pattern
This is enforced by the Code Analyzer ruleset (ExcessiveParameterList rule).
Performance
Start from platform limits, then apply implementation patterns that keep code bulk-safe and predictable under load.
Governor Limit Awareness
- Be aware of governor limits (SOQL queries, DML statements, CPU time, etc.)
- Use
Limitsclass to check current usage when needed - Design code to stay within limits
Example:
if (Limits.getQueries() < Limits.getLimitQueries() - 5) {
// Safe to perform query
}
Bulkification Patterns
Always write code that handles bulk operations (200+ records).
Bad Example:
for (Account acc : accounts) {
insert new Contact(AccountId = acc.Id, LastName = 'Test');
}
Good Example:
List<Contact> contacts = new List<Contact>();
for (Account acc : accounts) {
contacts.add(new Contact(AccountId = acc.Id, LastName = 'Test'));
}
insert contacts;
Query Optimization
- Only query fields you need
- Use appropriate WHERE clauses and filters
- Use
LIMITwhen appropriate - Avoid queries in loops
- Use
Security.stripInaccessible()for CRUD/FLS (see the Security standard for defaults and alternatives)
DML Best Practices
- Bulkify DML operations - Collect records and perform DML once
- Use Database methods -
Database.insert(),Database.update(), etc. for partial success handling - Use
Security.stripInaccessible()- Before DML operations
Example:
List<Account> accounts = new List<Account>();
// Populate accounts list
List<Database.SaveResult> results = Database.insert(
Security.stripInaccessible(AccessType.CREATABLE, accounts).getRecords(),
false // allOrNone = false for partial success
);
Transaction Control
Use transaction controls when a multi-step operation must succeed or fail as a unit.
For direct DML operations:
- Use
Databasemethods withallOrNoneparameter for transaction control - Use savepoints for complex transaction scenarios
- Handle partial DML success appropriately
Example:
Savepoint sp = Database.setSavepoint();
try {
insert accounts;
insert contacts;
} catch (Exception e) {
Database.rollback(sp);
throw e;
}
Change History
Version 1.0 - 2026-03-26
- Added initial version history tracking for this document.
Last Updated: 2026-03-26 Version: 1.0