The document introduces the Simple Trigger Pattern (STP) as a way to help developers quickly build great triggers that follow Apex trigger best practices. It begins by reviewing three key trigger best practices: having one trigger per object, keeping business logic out of triggers, and preventing trigger recursion using static variables. It then demonstrates the STP, which encapsulates these best practices into a template that provides a standardized structure for trigger handling. The STP code and documentation are available on GitHub to make it easy for developers to implement.
5. Trigger logic is usually…
• Complex
• Often mission critical!
• Entwined with other logic
• You don’t always control the other logic!
• High Volume
• Build for scale now…Don’t play catch-up later!
Why is This Important?
6. trigger AccountValidation on Account
(before insert, before update) {
// Do validation stuff...
}
trigger AccountRollup on Account
(after insert, after update) {
// Do rollup stuff...
}
trigger ShadowAccountBuilder on Account
(after insert, after update) {
// Do contact building stuff...
}
Why is this important?
• Multiple triggers don’t have a guaranteed order of
execution
• Code in multiple triggers leads to duplicated logic
• Duplicated logic is harder to maintain
Best Practice #1
“One Trigger Per Object”
7. trigger AccountTrigger on Account
(before insert, before update,
after insert, after update) {
if (Trigger.isBefore && Trigger.isInsert) {
// Do validation stuff...
}
else if (Trigger.isBefore && Trigger.isUpdate) {
// Do validation stuff...
}
else if (Trigger.isAfter && Trigger.isInsert) {
// Do rollup stuff...
// Do shadow account stuff...
}
else if (Trigger.isAfter && Trigger.isUpdate) {
// Do rollup stuff...
// Do shadow account stuff...
}
}
Recommendations
• Define a single “master” trigger
• Capture all “trigger actions” in the master trigger
• Use trigger context variables to determine what
trigger action is being executed
Best Practice #1
“One Trigger Per Object”
8. trigger AccountTrigger on Account
(before insert, before update,
after insert, after update) {
if (Trigger.isBefore && Trigger.isInsert) {
// Do validation stuff...
}
else if (Trigger.isBefore && Trigger.isUpdate) {
// Do validation stuff...
}
else if (Trigger.isAfter && Trigger.isInsert) {
// Do rollup stuff...
// Do shadow account stuff...
}
else if (Trigger.isAfter && Trigger.isUpdate) {
// Do rollup stuff...
// Do shadow account stuff...
}
}
Why is this important?
• Trigger code isn’t “full featured” Apex
• No access to static variables
• Logic in triggers is not reusable
Best Practice #2
“No Business Logic in Triggers”
9. trigger AccountTrigger on Account
(before insert, before update,
after insert, after update) {
AccountTriggerHandler
handler = new AccountTriggerHandler();
if (Trigger.isBefore && Trigger.isInsert) {
handler.beforeInsert();
}
else if (Trigger.isBefore && Trigger.isUpdate) {
handler.beforeUpdate();
}
else if (Trigger.isAfter && Trigger.isInsert) {
handler.afterInsert();
}
else if (Trigger.isAfter && Trigger.isUpdate) {
handler.afterUpdate();
}
}
Recommendations
• Implement a Trigger Handler Class
• Dispatch to specific “Action Handler” methods
• Leverage Service Classes for greater reusability
Best Practice #2
“No Business Logic in Triggers”
10. public class AccountTriggerHandler {
public void
afterInsert(list<Account> newAccounts,
map<Id, Account> newAccountsMap) {
// Create shadow accounts
list<Account> shadowAccs = new list<Account>();
for (Account newAccount : newAccounts) {
Account shadowAcc = new Account();
shadowAcc.Name = newAccount.Name
+ ‘ (Shadow)’;
shadowAccs.add(shadowAccount);
}
insert shadowAccs;
}
}
Why is this important?
• Sometimes trigger logic may execute more than
once in a single transaction
• Not good if you don’t want this to happen!
• Things that can cause recursion include
• Workflow fires that causes a field update
• Trigger performs DML on a same-type object
Best Practice #3
“Prevent Recursion Using Static Variables”
11. public class AccountTriggerHandler {
// Define a recursion check variable.
private static boolean aiFirstRun = true;
public void
afterInsert(list<Account> newAccounts,
map<Id, Account> newAccountsMap) {
// Check the “first run” flag.
if (aiFirstRun == false) {
return;
}
// Flip the “first run” flag.
aiFirstRun = false;
// Create shadow accounts...
createShadowAccounts(newAccounts);
}
}
Recommendations
• Use static variables to create a “gatekeeper” for your
trigger logic
• Solves recursion issues in large majority of use
cases
• Bonus Tip: Use private helper methods to keep
handler methods semantically clean and direct
Best Practice #3
“Prevent Recursion Using Static Variables”
12. Bulkified Code is not a trigger best practice...
Bulkified Code is an Apex best practice!
• Bulkification means your code can handle batches
of 200 records
• Service and Utility methods should be “bulkified from
birth”
• An Apex developer should always think “bulk first”
Wait a Minute…What About Bulkification?
14. Many Excellent Alternatives
• Tidy Pattern
• Simple Trigger Template
• TriggerX
• Hari Krishnan’s Framework
• Andrew Fawcett’s SOC
• Just to name a few...
Wait…Do we Really Need Another Trigger Pattern?
Simple
Trigger
Pattern
15. • One parent class
• One test class
• One Apex trigger template
• One Apex class template
• Encapsulates multiple best
practices
• Enables rapid development
• Provides a straightforward
standard that’s easy to implement
GitHub Repository
• bit.ly/SimpleTriggerPattern
GitHub Gist
• bit.ly/SimpleTriggerPatternGist
What Is It? What Does It Offer? Where Can I Get It?
Introducing the Simple Trigger Pattern (STP)
17. Three critical best practices for writing Apex triggers
• “One trigger per object”
• “No business logic in triggers”
• “Prevent recursion using static variables”
Introduced the Simple Trigger Pattern
Learned where to get and how to use the code
Review
18. GitHub Repo
• bit.ly/SimpleTriggerPattern
GitHub Gist
• bit.ly/SimpleTriggerPatternGist
Tidy Pattern
• bit.ly/TidyTriggerPattern
Simple Trigger Template
• bit.ly/SimpleTriggerTemplate
TriggerX
• bit.ly/TriggerXPattern
Hari Krishnan’s Pattern
• bit.ly/HariKrishnansPattern
GistBox
• GistBoxApp.com
Trigger Frameworks and Apex
Trigger Best Practices
• sforce.co/1IMaN3n
Andrew Fawcett on “Separation
of Concerns”
• bit.ly/FawcettBlogSOC
Simple Trigger Pattern (STP) Other Trigger Patterns Tools & Helpful Articles
Resources
Trigger logic is “high volume”
Called often
Processes records in “bulk”
Trigger logic is mission critical
Direct result of business needs
Trigger logic has to play nice with everybody
Workflows
Processes
Other triggers