20
Build Great Triggers Quickly with STP (the Simple Trigger Pattern) Vivek M. Chawla Salesforce MVP | Senior Software Developer – Intuit @VivekMChawla

Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

Embed Size (px)

Citation preview

Page 1: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

 Vivek M. Chawla  Salesforce MVP | Senior Software Developer – Intuit  @VivekMChawla

Page 2: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

Vivek M. Chawla Salesforce MVP | Senior Software Engineer, Intuit | @VivekMChawla

Page 3: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

  Review Three Key Trigger Best Practices

  Introduce the Simple Trigger Pattern (STP)

  Demo

  Q & A

Overview

Page 4: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

Best Practices for Apex Triggers

Page 5: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

 Trigger best practices are important because 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?

Page 6: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

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... }

 Core Problems

•  Unknown order of execution

•  Duplicated business logic

•  Code is harder to maintain

Best Practice #1  “One Trigger Per Object”

Page 7: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

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”

Page 8: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

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... } }

 Core Problems

•  Code is harder to maintain

•  Static variables aren’t available in trigger files

Best Practice #2  “No Business Logic in Triggers”

Page 9: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

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

•  Trigger Handler should leverage Service Classes for greater reusability

Best Practice #2  “No Business Logic in Triggers”

Page 10: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

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; } }

 Core Problem

•  Something causes your trigger logic to execute more than once

•  Trigger performs DML on a same-type object

•  Workflow fires that causes a field update

Best Practice #3  “Prevent Recursion Using Static Variables”

Page 11: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

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”

Page 12: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

 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

•  An Apex developer should always think “bulk first”

•  Service and Utility methods should be “bulkified from birth”

Wait a Minute…What About Bulkification?

Page 13: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

The Simple Trigger Pattern (STP)

Page 14: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

 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

Page 15: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

•  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)

Page 16: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

Demo

Page 17: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

 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

Page 18: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

 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

Page 19: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

Q&A @VivekMChawla

Page 20: Build Great Triggers Quickly with STP (the Simple Trigger Pattern)

Thank you