Mastering Apex Triggers: Patterns for Scalable and Maintainable Automation

 

Introduction

Apex triggers are powerful tools for automating business processes in Salesforce. However, without proper structure, triggers can become hard to maintain and prone to errors. In this post, we’ll look at advanced patterns and best practices for writing scalable and maintainable Apex triggers.

Common Problems with "Trigger Hell"

  • Multiple triggers on the same object causing unpredictable execution order.
  • Logic directly in triggers, making code hard to test and reuse.
  • Difficulty in handling bulk updates and governor limits.

The One Trigger Per Object Pattern

Best Practice:
Always write a single trigger per object and delegate logic to handler classes.

Example Structure

// OpportunityTrigger.trigger trigger OpportunityTrigger on Opportunity (before insert, before update, after insert) { OpportunityTriggerHandler handler = new OpportunityTriggerHandler(); if (Trigger.isBefore) { handler.beforeInsert(Trigger.new); handler.beforeUpdate(Trigger.new, Trigger.oldMap); } if (Trigger.isAfter) { handler.afterInsert(Trigger.new); } }
// OpportunityTriggerHandler.cls public class OpportunityTriggerHandler { public void beforeInsert(List<Opportunity> newOpps) { // Add business logic here for (Opportunity opp : newOpps) { if (opp.StageName == 'Prospecting') { opp.Description = 'Initial stage'; } } } public void beforeUpdate(List<Opportunity> newOpps, Map<Id, Opportunity> oldOpps) { // Business logic for before update } public void afterInsert(List<Opportunity> newOpps) { // Business logic for after insert } }

Bulkification and Governor Limits

Always write trigger logic to handle bulk operations:

// Example: Bulk assigning a field value for (Opportunity opp : newOpps) { opp.Custom_Field__c = 'Value'; }
  • Avoid SOQL/DML inside loops.
  • Use collections and maps for efficient processing.

Unit Testing Trigger Handlers

Keep your trigger handler methods public and testable:

@isTest private class OpportunityTriggerHandlerTest { @isTest static void testBeforeInsert() { List<Opportunity> opps = new List<Opportunity>{ new Opportunity(Name='Test', StageName='Prospecting', CloseDate=Date.today()) }; OpportunityTriggerHandler handler = new OpportunityTriggerHandler(); handler.beforeInsert(opps); System.assertEquals('Initial stage', opps[0].Description); } }

Conclusion

By following these patterns—one trigger per object, using handler classes, and bulkifying your logic—you’ll create Apex automation that is reliable, scalable, and easy to maintain. Advanced developers should always prioritize code quality, testability, and future-proofing in their Salesforce automation.


Have your own trigger patterns or tips? Share them in the comments!

0 Comments

Post a Comment

Post a Comment (0)

Previous Post Next Post