Introduction
In Salesforce, a “trigger class” (often called a trigger handler or Apex handler class) is an Apex class that contains the business logic invoked by an Apex trigger. Using a trigger class separates trigger orchestration from implementation details, improving maintainability, testability, and scalability of your Salesforce code.
Why use a trigger class?
Trigger classes are critical for professional Apex development. Key benefits include:
- Separation of concerns: Keep trigger files small and focused on event handling (before insert, after update, etc.), while the complex business logic lives inside a handler class.
- Reusability: A handler class can be reused across multiple triggers or called from other Apex code (Batch, Schedulable, REST services).
- Testability: Isolated methods in a class are easier to unit test using @isTest classes. You can mock or stub dependencies more easily.
- Bulkification: Well-structured handler classes encourage bulk-safe patterns (working with collections rather than single records) to respect Salesforce governor limits.
- Readability and maintainability: Clear structure and consistent trigger frameworks make ongoing support and enhancements simpler for teams.
Common trigger class pattern
A typical pattern is to have a short trigger that delegates to a handler class. The trigger only constructs context information and calls the handler:
// Trigger (AccountTrigger.trigger)
trigger AccountTrigger on Account (before insert, before update, after insert, after update) {
AccountTriggerHandler handler = new AccountTriggerHandler();
if (Trigger.isBefore) {
if (Trigger.isInsert) handler.beforeInsert(Trigger.new);
if (Trigger.isUpdate) handler.beforeUpdate(Trigger.new, Trigger.oldMap);
}
if (Trigger.isAfter) {
if (Trigger.isInsert) handler.afterInsert(Trigger.new);
if (Trigger.isUpdate) handler.afterUpdate(Trigger.newMap, Trigger.oldMap);
}
}
Example handler class
Handler classes group methods according to trigger events and include bulk-safe logic:
public with sharing class AccountTriggerHandler {
public void beforeInsert(List
// Bulk-safe iteration and field assignments
for (Account acc : newAccounts) {
if (String.isBlank(acc.Industry)) {
acc.Industry = 'Unknown';
}
}
}
public void beforeUpdate(List
// Compare new and old values using oldMap for selective processing
for (Account acc : newAccounts) {
Account oldAcc = oldMap.get(acc.Id);
if (acc.AnnualRevenue != oldAcc.AnnualRevenue) {
// perform actions or collect ids for a single query
}
}
}
public void afterInsert(List
// Example: enqueue asynchronous work or perform non-DML operations
}
public void afterUpdate(Map
// Example: handle related records updates using a single SOQL outside loops
}
}
Best practices
Follow these best practices when using trigger classes:
- Keep triggers slim — only delegate to handler methods.
- Write bulk-safe code: avoid SOQL/DML inside loops, use collections, and minimize CPU/heap usage.
- Use context-specific methods (beforeInsert, afterUpdate) instead of putting all logic in one method.
- Implement a trigger framework or a simple static guard to prevent recursion and control order of operations.
- Use one handler class per object (or well-structured service classes) to keep responsibilities clear.
- Respect sharing rules appropriately: use “with sharing” or “without sharing” intentionally.
Common pitfalls to avoid
Watch out for these issues when implementing trigger classes:
- Unintentionally causing recursive triggers — use static booleans or framework patterns to avoid repeated execution.
- Violating governor limits by performing SOQL/DML in loops.
- Mixing UI/business rules — keep concerns separated so that bulk operations (API/Bulk API) don’t break.
Conclusion
In short, trigger classes (handler classes) are used to encapsulate Apex business logic invoked by triggers. They provide better structure, reusability, testability, and enable bulk-safe, maintainable code in Salesforce. For interviews, be ready to explain the pattern, show a short code example, and discuss how your handler prevents recursion and handles large data volumes.
Leave a Reply