top of page

Trigger Handler Patterns Introduction

Writer: Sowed ConsultingSowed Consulting

Updated: Mar 13

The Trigger Handler Pattern in Salesforce is a best practice for managing Apex Triggers efficiently, ensuring scalability, maintainability, and performance. Here are the best practices for implementing the Trigger Handler Pattern:


1. Use One Trigger Per Object

Avoid multiple triggers on the same object.

Use a single trigger that delegates logic to a handler class.

📌 Why? Ensures execution order control and prevents recursion issues.


2. Create a Trigger Handler Class

Move all logic from the trigger into a separate Apex class (handler).

The trigger should only call methods from the handler.

📌 Why? Improves code readability, modularity, and testability.


Example:


trigger AccountTrigger on Account (before insert, before update) {

AccountTriggerHandler handler = new AccountTriggerHandler();

if (Trigger.isBefore && Trigger.isInsert) {

handler.beforeInsert(Trigger.new);

}

if (Trigger.isBefore && Trigger.isUpdate) {

handler.beforeUpdate(Trigger.new, Trigger.oldMap);

}

}


3. Use Context-Specific Methods

In the handler class, define separate methods for each trigger event.


Example handler class:


public class AccountTriggerHandler {

public void beforeInsert(List<Account> newAccounts) {

// Logic for before insert

}

public void beforeUpdate(List<Account> updatedAccounts, Map<Id, Account> oldAccountMap) {

// Logic for before update

}

}


📌 Why? Avoids cluttering a single method with multiple operations.


4. Bulkify All Operations

Always work with lists instead of single records.

Use Maps and Sets for efficiency.

Avoid SOQL inside loops and DML inside loops.


Example:


public void beforeUpdate(List<Account> updatedAccounts, Map<Id, Account> oldAccountMap) {

Set<Id> accountIds = new Set<Id>();

for (Account acc : updatedAccounts) {

accountIds.add(acc.Id);

}

Map<Id, CustomObject__c> relatedData = new Map<Id, CustomObject__c>(

[SELECT Id, Name FROM CustomObject__c WHERE Account__c IN :accountIds]

);


for (Account acc : updatedAccounts) {

if (relatedData.containsKey(acc.Id)) {

acc.Some_Field__c = relatedData.get(acc.Id).Name;

}

}

}


📌 Why? Improves performance and avoids governor limits.


5. Prevent Recursive Trigger Execution

Use a Static Boolean Variable or Set<Id> to prevent recursion.


Example:


public class AccountTriggerHandler {

private static Boolean isTriggerExecuted = false;


public void beforeInsert(List<Account> newAccounts) {

if (isTriggerExecuted) return;

isTriggerExecuted = true;


// Logic here

}

}


📌 Why? Prevents infinite loops when updates trigger another update.


6. Implement Custom Metadata for Configurable Logic

Use Custom Metadata or Custom Settings to control behavior dynamically.

📌 Why? Allows turning features on/off without code changes.


7. Write Unit Tests for the Handler Class

Test each handler method independently.

Use Test.startTest() and Test.stopTest().


Example test:


@isTest

private class AccountTriggerHandlerTest {

@isTest

static void testBeforeInsert() {

List<Account> accounts = new List<Account>{

new Account(Name = 'Test Account')

};

Test.startTest();

insert accounts;

Test.stopTest();


System.assert(accounts[0].Id != null, 'Account should be inserted');

}

}


📌 Why? Ensures trigger logic works correctly and remains bulk-safe.


Final Thoughts

  • One trigger per object

  • Use a separate handler class

  • Bulkify operations

  • Prevent recursion

  • Write tests for trigger logic


Following these best practices will make your Salesforce org scalable, efficient, and easy to maintain!

 
 
 

コメント

5つ星のうち0と評価されています。
まだ評価がありません

評価を追加
Sowed Consulting Company Logo

© 2025 Sowed Consulting, LLC. All rights reserved. 

Terms, Conditions, Privacy Policy.

  • salesforce_appexchange_edited
  • LinkedIn
  • Youtube
We are Salesforce Experts who partner with you to bring your ideas to life, to modernize your operations, and to grow your business.
bottom of page