Overview:
A trigger handler framework is a way to remove logic from your triggers and enforce consistency across the platform. The framework itself will do the heavy lifting for you in terms of figuring out which kind of trigger is currently running and firing the correct logic.
Triggers should (IMO) be logic-less. Putting logic into your triggers creates UN-testable, difficult-to-maintain code. It's widely accepted that a best-practice is to move trigger logic into a handler class.
But the most important part of this framework is that it's minimal and simple to use.
Advantages of using a trigger framework:
- Removing trigger logic from the trigger makes unit testing and maintenance much easier.
- Standardizing triggers means all of your triggers work in a consistent way.
- A single trigger per object gives full control over order of execution.
- Prevention of trigger recursion.
- It makes it easy for large teams of developers to work across an org with lots of triggers. I recently worked on an org which had triggers on around fifty objects, and the fact that every trigger was implemented in a consistent manner made it easy to go in and make changes or add new triggers.
The interface
The interface dictates which methods every trigger handler must implement, even if these methods have no code in them. By implementing the methods in this class, the Trigger Dispatcher (discussed below) can be confident that the trigger handler has a method for each of these events:
- Before/After Insert
- Before/After Update
- Before/After Delete
- After Undelete
- IsDisabled
Here’s the code:
public interface ITriggerHandler
{
void BeforeInsert(List<SObject> newItems);
void BeforeUpdate(Map<Id, SObject> newItems, Map<Id, SObject> oldItems);
void BeforeDelete(Map<Id, SObject> oldItems);
void AfterInsert(Map<Id, SObject> newItems);
void AfterUpdate(Map<Id, SObject> newItems, Map<Id, SObject> oldItems);
void AfterDelete(Map<Id, SObject> oldItems);
void AfterUndelete(Map<Id, SObject> oldItems);
Boolean IsDisabled();
}
The Dispatcher
The dispatcher is responsible for making sure all of the applicable methods on your trigger handler are called, depending on the current trigger context. It also contains a check to make sure that the trigger has not been disabled. If the trigger has been disabled (more on this below), then the trigger events will not be fired (See lines 10/11).
Again, this is part of the framework and you do not need to change this code in any way. Just make sure the class is in your org.
Here’s the code:
public class TriggerDispatcher {
/* Call this method from your trigger, passing in an instance of a trigger handler which implements ITriggerHandler.
This method will fire the appropriate methods on the handler depending on the trigger context.
*/
public static void Run(ITriggerHandler handler) {
// Detect the current trigger context and fire the relevant methods on the trigger handler:
// Before trigger logic
if (Trigger.IsBefore )
{
if (Trigger.IsInsert)
handler.BeforeInsert(trigger.new);
if (Trigger.IsUpdate)
handler.BeforeUpdate(trigger.newMap, trigger.oldMap);
if (Trigger.IsDelete){
handler.BeforeDelete(trigger.oldMap);
}
}
// After trigger logic
if (Trigger.IsAfter)
{
if (Trigger.IsInsert)
handler.AfterInsert(Trigger.newMap);
if (Trigger.IsUpdate)
handler.AfterUpdate(trigger.newMap, trigger.oldMap);
if (trigger.IsDelete)
handler.AfterDelete(trigger.oldMap);
if (trigger.isUndelete)
handler.AfterUndelete(trigger.oldMap);
}
}
}
Creating a Trigger Handler
This trigger framework bundles a single TriggerHandler base class that you can inherit from in all of your trigger handlers. The base class includes context-specific methods that are automatically called when a trigger is executed.
Here’s the code:
public class OpportunityTriggerHandler implements ITriggerHandler {
public void BeforeInsert(List<SObject> newItems){ // Your Logic}
public void BeforeUpdate(Map<Id, SObject> newItems, Map<Id, SObject> oldItems){ // Your Logic}
public void BeforeDelete(Map<Id, SObject> oldItems){ // Your Logic}
public void AfterInsert(Map<Id, SObject> newItems){ // Your Logic}
}
public void AfterUpdate(Map<Id, SObject> newItems, Map<Id, SObject> oldItems){ // Your Logic}
public void AfterDelete(Map<Id, SObject> oldItems){ // Your Logic}
public void AfterUndelete(Map<Id, SObject> oldItems){ // Your Logic}
}
Hooking up the trigger
Now we just need to hook the trigger itself in. Create a trigger on your object and make sure it fires on all events.We only need a single line of code to hook the trigger handler in via the dispatcher. See below.
Here’s the code:
trigger OpportunityTrigger on Opportunity (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
TriggerDispatcher.Run(new OpportunityTriggerHandler());
}
We simply call the static method on the TriggerDispatcher, and pass it a new instance of our OpportunityTriggerHandler. The framework takes care of the rest.
This may have seemed like a bit of work, but going forward you would only need to create the triggerhandler and one line trigger for any future triggers.
Thank You...😄😄😄
--------------------------------------------------------------------------------------------------------------------------