This post is also available in: Español (Spanish)
“Keep triggers logic-less”. That’s what you have probably read a lot of times when surfing on the Internet to see how to write your first triggers. To achieve this, you need to apply a “framework”, which is actually a way of writing your code in order to keep it simple. After looking at all those articles and tutorials, I found out that this is my preferred easy-to-understand-trigger-framework.
What do you mean by logic-less trigger?
I basically mean that your trigger should only call methods developed in another handler class. It should be written in a way in which you can easily know what is going to happen every time your trigger is fired. For instance:
trigger ContactTrigger on Contact (before update, after update, before insert, after insert) {
if(Trigger.isBefore && (Trigger.isInsert || Trigger.isUpdate)){
if (checkRecursive.runOnce()){
ContactHandler.isBeforeInsertAndUpdate(Trigger.new);
}
}
}
As you can see here, instead of writing all the logic (that is: all the things we want it to do, with all its lines and instructions) within the trigger, we make use of a “contact handler” class to call the methods we need in each case.
With this schema, you can easily control when things happen, and in practice, you almost don’t need to touch your trigger file when you want to change a certain behaviour. You just have to address to your handler class and/or helpers.
The framework structure
The framework structure I use, usually follows this pattern:
- Trigger (.trigger file)
- Handler Class
- Helper Class
- Handler Class
The trigger contains the situations in which the trigger must fire a certain routine of actions. These routines are handled by the Handler Class.
The Handler Class contains the routines we need to call each time. Using descriptive names on its methods will help us identify when to apply each. An example:
Public with sharing class ContactHandler {
public static void isBeforeInsertAndUpdate(List<Contact> newContacts){
developmentValidator.updateDevelopmentId(newContacts);
}
}
When you have “routines” that perform the same methods, having a Helper Class that contains all of these can be helpful. Sometimes this helper class is not needed if your trigger is just for a few unique cases. But if you consider that your trigger will tend to grow and reuse the same methods, instead of having a Handler full of copied code, maybe you can consider having this Helper Class.
You can also incluse all the methods within the handler class and calling these locally. But the helper will improve your code, looking cleaner.
A full example of a trigger framework
The trigger
With this approach, we finally get a logic-less trigger code in which we control specifically when does our trigger fire.
trigger saleCaseUnitTrigger on Sale_case_unit__c (after insert, before insert, after update, before update, after delete, before delete) {
if(Trigger.isInsert && Trigger.isAfter){
saleCaseUnitHandler.isAfterInsert();
}
if(Trigger.isUpdate && Trigger.isBefore){
if (checkRecursive.runOnce()){
saleCaseUnitHandler.isBeforeUpdate();
}
}
if(Trigger.isDelete && Trigger.isAfter){
saleCaseUnitHandler.isAfterDelete();
}
}
The Handler class
Sometimes, if your trigger is not too big, you may drop all your logic in this class. But chances are that you will have methods that will be repeated in several methods.
The aim of this handler class is to define the steps that the trigger has to launch in every specific case and have no doubts about it.
public with sharing class saleCaseUnitHandler {
public static void isAfterInsert(){
SaleCaseUnitHandlerHelper.checkIfListingIsAvailable();
}
public static void isBeforeUpdate(){
SaleCaseUnitHandlerHelper.checkIfListingIsInAnotherSaleCase(Trigger.new);
}
public static void isAfterDelete(){
saleCaseUnitHandlerHelper.changeListingStatusWhenSCUDeleted(Trigger.old);
}
}
The Helper Class
In this class we code all the methods that will be called buy the handler on each case.
public with sharing class SaleCaseUnitHandlerHelper {
public static void checkIfListingIsAvailable(){
// Your actions...
}
public static void checkIfListingIsInAnotherSaleCase(List<Sale_Case_Unit__c> updatedSCUs) {
// Your actions...
}
public static void changeListingStatusWhenSCUDeleted(List<Sale_Case_Unit__c> deletedSCUs) {
// Your actions...
}
}
If you know other easy-to-understand trigger frameworks for beginners, please, feel free to comment and suggest below.
Peace and Code
Nadine.