Skip to main content

Apex Best Practices

✅ Apex Best Practices: Separation of Concerns & Modular Coding

Writing clean, scalable Apex code requires following key best practices such as Separation of Concerns (SoC) and Modular Coding. These help you build maintainable, testable, and reusable Salesforce applications.


๐Ÿ“Œ What is Separation of Concerns?

Separation of Concerns means dividing code into distinct sections, each handling a specific responsibility. In Apex, this typically involves:

  • ๐Ÿ” Keeping Triggers free of business logic
  • ๐Ÿง  Moving logic to Handler and Helper classes
  • ๐Ÿ”ง Using Utility classes for common logic
---

๐Ÿ“ Recommended Structure

/triggers
  ContactTrigger.trigger

/classes
  ContactTriggerHandler.cls
  ContactHelper.cls
  ValidationUtils.cls
---

๐Ÿงฉ Example: Good Modular Design

1️⃣ Trigger (Only Entry Point)

ContactTrigger.trigger

trigger ContactTrigger on Contact (before insert) {
    ContactTriggerHandler.handleBeforeInsert(Trigger.new);
}
  

2️⃣ Handler Class

ContactTriggerHandler.cls

public class ContactTriggerHandler {
    public static void handleBeforeInsert(List newContacts) {
        ContactHelper.setDefaultTitle(newContacts);
    }
}
  

3️⃣ Helper Class

ContactHelper.cls

public class ContactHelper {
    public static void setDefaultTitle(List contacts) {
        for(Contact c : contacts) {
            if(String.isBlank(c.Title)) {
                c.Title = 'Customer';
            }
        }
    }
}
  
---

๐Ÿ” Comparison Table

Approach Without SoC With SoC (Best Practice)
Trigger Contains all logic Delegates to handler
Handler Not used Controls flow based on event
Helper Logic mixed into trigger Contains actual business logic
---

๐Ÿงช Benefits of Modular Design

  • ✅ Easier to test individual components
  • ✅ Encourages code reuse
  • ✅ Simplifies debugging and maintenance
  • ✅ Enhances team collaboration
---

๐Ÿ“‹ Final Best Practices

  • Use TriggerHandler classes for all triggers
  • Move logic to Helper and Service classes
  • Use utility classes for reusable functions (e.g., validation, formatting)
  • Keep classes focused on a single responsibility
  • Use meaningful method and variable names