Experience Salesforce
Best Practice in Triggers
What You’ll Learn
- Best Practices In Apex Triggers
Topics
- Basics of Triggers
- When to use triggers
- Types of Apex Triggers in Salesforce
- Trigger Order of Execution
- Trigger Context Variables in Salesforce
- Trigger.new in Salesforce| Context Variables in Apex Triggers
- Trigger.old in Salesforce | Context Variables in Apex Triggers
- Trigger.newMap in Salesforce| Context Variables in Apex Triggers
- Trigger.oldMap in Salesforce| Context Variables in Apex Triggers
- Trigger Exceptions
- Best Practice in Triggers
- Trigger Helper Class Pattern
Apex Triggers can be difficult to execute successfully if the right precautions are not taken. Salesforce recommends the use of Apex Trigger best practices to avoid recursion. Recursion is caused when a single trigger action is executed again and again by automation. This poses a risk of hitting Governor Limits due to recursive Apex.
There are various best practice concepts that we need to keep in mind while writing triggers. Here are some of them that can be applied while writing apex code for best performance of trigger:
1. Always create only one Trigger per object.
2. Create logic-less Triggers and use Helper Class Design Pattern in which the helper class will
contain all the logic.
3. Create context-specific handler methods in the Helper Class.
4. Bifurcate “insert” and “update” Trigger logic contexts and create two different methods in the
Trigger’s helper class.
Bulkified Triggers and Helper class are two major practices taht are accepted and used widely in the Salesforce community. In this chapter we will cover the Bulkified Trigger practice.
What Are Bulkified Triggers?
Bulkified Triggers are a pattern of writing Apex Triggers in a bulk design so as to produce a better performance. It also saves the server resources and thus it is considered a best practice of Apex test class. Using the bulkified code in Apex helps in processing a large number of records efficiently while keeping everything under the governor limits.
Characteristics Of Bulkified Trigger
Here are some major characteristics of Bulkified Trigger that would help in better understanding. It can be used for:
- Operating on all records of the trigger.
- Performing SOQL & DML on collections of sObjects instead of single sObject at a time.
- Utilizing maps to hold query results organized by record id. Avoid query within a query and save records in the map which later can be accessed through a map rather than using SOQL.
- Using Sets to isolate distinct records.
Examples of Bulkified Trigger
Example 1
Avoid creating Triggers that work only for individual records but not for entire datasets:
trigger testTrigger on Acount__c(before insert) { Acount__c acc = Trigger.New[0]; acc.Address__c = ‘Temporary Address’; } |
Create Triggers that use loops to help iterate over a list of records within a transaction:
trigger testTrigger on Acount__c(before insert) { integer i = 1; for (Acount__c acc: Trigger.new) { acc.Address__c = ‘Test Address ‘ + I; i++; } } |
Example 2
In this code, let’s assume 200 Account records are updated, so the “for” loop would iterate over 200 records.
trigger BranchTrigger on Branch__c(before update) { for (Branch__c br: Trigger.new) { List < Acount__c > accList = [SELECT Name, Account_Name__c, Address__c, Balance__c FROM Acount__c WHERE Acount_of_Branch__c = : br.id ]; System.debug(accList); // Perform specified logic with queried records } } |
Now let’s look at a good example of querying bulk data and iterating it.
trigger BranchTrigger on Branch__c(before update) { List < Acount__c > accList = [SELECT Name, Account_Name__c, Address__c, Balance__c FROM Acount__c WHERE Acount_of_Branch__c IN: Trigger.New ]; System.debug(accList); for (Acount__c acc: accList) { // Perform specified logic with queried records } } |
Example 3
DML statements are also bound by Governor Limits; you can call only 150 DML operations in a transaction.
trigger BranchTrigger on Branch__c(before update) { List < Acount__c > accList = [SELECT Name, Account_Name__c, Address__c, Balance__c FROM Acount__c WHERE Acount_of_Branch__c IN: Trigger.New ]; System.debug(accList); integer i = 0; for (Acount__c acc: accList) { acc.Address__c = ‘Test Address ‘ + i; i++; update acc; } } |
Let’s look at a correct coding example where we have instantiated another Account object list called “accToUpdate.”
trigger BranchTrigger on Branch__c(before update) { List < Acount__c > accToUpdate = new List < Acount__c > (); List < Acount__c > accList = [SELECT Name, Account_Name__c, Address__c, Balance__c FROM Acount__c WHERE Acount_of_Branch__c IN: Trigger.New ]; System.debug(accList); integer i = 0; for (Acount__c acc: accList) { acc.Address__c = ‘Test Address ‘ + i; i++; accToUpdate.add(acc); } if (!accToUpdate.isEmpty()) { update accToUpdate; } } |
Need Extra Support? Our FREE study materials have got you covered.
Our expert-prepared study materials provide the answers you need. Clear your doubts and improve your skills with detailed notes from industry professionals.