0

I'm curious between Version 1 and Version 2, which of these trigger structures is more efficient? Or is there is another structure that is better?

When using a for loop I can check requirements of the record that is causing the trigger to fire. Such as making sure the picklist contains the right value or that a field is not empty. For this case is Version 1 or 2 preferred?

If there is a choice, is it better to work with a list(version 3) or an individual record(version 1 and 2)?

Version 1

trigger AcctTrigger on Account(before insert, before update) 
{
    for(Account a : trigger.new)
    {
       if(trigger.isBefore && trigger.isInsert)
       {
          //call handler(a)
       }
       if(trigger.isBefore && trigger.isUpdate)
       {
          //call handler(a)
       }
    }
}

Version 2

trigger AcctTrigger on Account(before insert, after insert, after update) 
{
   if(trigger.isBefore && trigger.isInsert)
   {
      for(Account a : trigger.new)
      {
         //call handler(a)
      }
   }
   if(trigger.isBefore && trigger.isUpdate)
   {
      for(Account a : trigger.new)
      {
         //call handler(a)
      }
   }
}

Version 3

trigger AcctTrigger on Account(before insert, before update) 
{
    if(trigger.isBefore && trigger.isInsert)
    {
       //call handler(trigger.new)
    }
    if(trigger.isBefore && trigger.isInsert)
    {
       //call handler(trigger.new)
    }
}
1
  • 2
    Stirctly speaking, checking picklists and not empty conditions would be things you should probably be handling through validation rules rather than a trigger.
    – Derek F
    Commented Oct 5, 2020 at 17:22

2 Answers 2

4

You could use the newer Trigger.operationType enum.

trigger AcctTrigger on Account(before insert, after insert, after update) {
    switch on Trigger.operationType {
        when BEFORE_INSERT, BEFORE_UPDATE {
            // call your before handler
        }
        when AFTER_INSERT {
            // call your after handler
        }
        when else {
            // this shouldn't happen
        }
    }
}
4
  • do you know what the advantage is of this newer version?
    – ThatGuy
    Commented Oct 5, 2020 at 17:40
  • It's just more explicit... you specific the exact situations which should run your handler, and nothing else
    – Charles T
    Commented Oct 5, 2020 at 17:58
  • what if you have to run a query in your handler for each item in the trigger.new? This would throw an exception. At that point would you then need to use version 1 or 2?
    – ThatGuy
    Commented Oct 6, 2020 at 13:09
  • "what if you have to run a query in your handler for each item in the trigger.new?" - first you should bulkify, not run a query per item. But second, if you write one handler method that expects to be able to handle both insert & update then you design it for both scenarios. If you need to create one version per scenario, do that and modify the switch statement accordingly.
    – Charles T
    Commented Oct 6, 2020 at 16:07
2

Of the three structures shown here, only Version 3 is best practice. Your trigger should never iterate over context variables and call handler methods with single sObjects, because this makes it impossible for your handler to be meaningfully bulkified.

That said, there are two superior patterns. One is what Charles articulated, using a switch on statement with Trigger.operationType. The other is to use a trigger handler framework that abstracts away the dispatch operation, so that you do not repeat the same boilerplate logic in each trigger. Kevin O'Hara's trigger framework, for example, moves all dispatch logic into the trigger handler base class, so you don't need to see or write it.

1
  • or fflib Domain pattern as an alternative trigger framework++
    – cropredy
    Commented Oct 7, 2020 at 2:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .