Apex Best Practices – Bulkification, Governor Limits & Clean Code

Writing efficient Apex code is crucial for building scalable Salesforce applications. This guide covers the three pillars of Apex best practices: bulkification, respecting governor limits, and maintaining clean code.

1. Bulkification: The Golden Rule

Bulkification means writing code that processes multiple records at once instead of one-by-one. Salesforce can trigger your code for 1-200 records in a single execution.

❌ Bad - Using loops with DML


for (Account acc : accounts) {
    acc.Active__c = true;
    update acc;  // DML in loop! Hits limit
}
  

✅ Good - Bulk DML outside loops


List<Account> accountsToUpdate = new List<Account>();
for (Account acc : accounts) {
    acc.Active__c = true;
    accountsToUpdate.add(acc);
}
update accountsToUpdate;  // Single DML call
  

2. Respecting Governor Limits

Salesforce enforces limits to protect the platform's stability. The most common limits are:

❌ Bad - SOQL in loop


for (Contact con : contacts) {
    List<Opportunity> opps = [SELECT Id FROM Opportunity WHERE AccountId = :con.AccountId];
    // Too many queries!
}
  

✅ Good - Query once, process data


Map<Id, List<Opportunity>> oppsByAccount = new Map<Id, List<Opportunity>>();

for (Opportunity opp : [SELECT Id, AccountId FROM Opportunity]) {
    if (!oppsByAccount.containsKey(opp.AccountId)) {
        oppsByAccount.put(opp.AccountId, new List<Opportunity>());
    }
    oppsByAccount.get(opp.AccountId).add(opp);
}
  

3. Clean Code Principles

Use Meaningful Names


// Bad
List<Account> a = new List<Account>();

// Good
List<Account> activeAccounts = new List<Account>();
  

Keep Methods Small and Focused


// Bad - Method does too much
public void processAccounts(List<Account> accounts) {
    // validation
    // processing
    // dml
}

// Good - Single responsibility
private void validateAccounts(List<Account> accounts) { }
private void calculateMetrics(List<Account> accounts) { }
  

Use Comments Wisely


// Bad - States the obvious
int count = 0;  // increment count

// Good - Explains the WHY
// Exclude test records from billing calculation
List<Account> billableAccounts = [SELECT Id FROM Account WHERE IsTest__c = false];
  

4. Error Handling Best Practice


try {
    update records;
} catch (DmlException e) {
    System.debug('Update failed: ' + e.getMessage());
    throw new CustomException('Failed to update records');
}
  

Key Takeaways