• Home
  • About
    • Leadership
    • Partners
    • Blogroll
  • Force-Squared Blog
    • Tips and Tricks
    • Configuration
    • Development
  • Support
    • Knowledge Base
    • Submit a Case
  • Is It Dreamforce Yet?

X-Squared On Demand

Salesforce solution development

  • Home
  • About
    • Leadership
    • Partners
    • Blogroll
  • Force-Squared Blog
    • Tips and Tricks
    • Configuration
    • Development
  • Support
    • Knowledge Base
    • Submit a Case
  • Is It Dreamforce Yet?
  • Tips and Tricks
  • Configuration
  • Development
You are here: Home / Salesforce CRM / Development / Apex / Pulling Code Out of Triggers

Pulling Code Out of Triggers

May 18, 2009 by David Schach 6 Comments

To date, triggers have only been accessible on each object's setup page, leading to a lot of hunting for code within the Salesforce CRM application. Even in Eclipse, switching between the Class and Trigger folders for a given project can be a pain.

These pains can partially be alleviated by keeping all Apex code in one place--as Apex Classes. With the addition of a consolidated trigger list in Summer09, some may feel that this post is superfluous, but consolidating code in one place, combined with the trigger list, will lead to a better development, debugging, and org administration experience.

First, here's a sample trigger (written by Jeff Douglas):

trigger AddOwnerColor on Account (before insert, before update) {

    // create a set of all the unique ownerIds
    Set<Id> ownerIds = new Set<Id>();
    for (Account a : Trigger.new)
        ownerIds.add(a.OwnerId);    

    // query for all the User records for the unique userIds in the records
    // create a map for a lookup / hash table for the user info
    Map<Id, User> owners = new Map<Id, User>([Select Favorite_Color__c from User Where Id in: ownerIds]);   

    // iterate over the list of records being processed in the trigger and
    // set the color before being inserted or updated
    for (Account a : Trigger.new)
        a.Owner_Favorite_Color__c = owners.get(a.OwnerId).Favorite_Color__c; 
}

Let's pull the code from the trigger into an Apex Class and leave a reference to that class & method in the trigger. We need to pass the list Trigger.new as a parameter to the new class's method:

The trigger:

trigger AddOwnerColor on Account (before insert, before update) {
AccountTriggers.AddOwnerColor(Trigger.new);
}
And the class:
public class AccountTriggers {
    public static void AddOwnerColor(Account[] accts) {

    // create a set of all the unique ownerIds
    Set<Id> ownerIds = new Set<Id>();
    for (Account a : accts)
        ownerIds.add(a.OwnerId);    

    // query for all the User records for the unique userIds in the records
    // create a map for a lookup / hash table for the user info
    Map<Id, User> owners = new Map<Id, User>([Select Favorite_Color__c from User Where Id in: ownerIds]);   

    // iterate over the list of records being processed in the trigger and
    // set the color before being inserted or updated
    for (Account a : accts)
        a.Owner_Favorite_Color__c = owners.get(a.OwnerId).Favorite_Color__c; 
    } // close AddOwnerColor
}
While this may seem trivial, it has a few advantages:

  • Easier to work in Eclipse (all code in the Classes section)
  • Easier to write test code (can see tests and their associated methods in one place)
  • Can promote code reuse by allowing other classes and triggers to call the same method.
  • For those who like to include test code in the same class as the regular Class, this allows them to do so.

There's a catch (there always is):

You should comment into your Class which trigger is calling the class because otherwise, it is almost impossible to see at a glance where the code flows. This will especially help when writing and debugging tests.

Just a matter of personal style: It may be a good idea to write an Apex Class for each object's triggers (such as class AccountTriggers above). Code reuse is still possible, but it can track where triggers were originally used.

Happy coding!

Related

Filed Under: Apex, Development, Salesforce, Summer 09 Tagged With: Apex, Eclipse IDE, Force.com Platform

← Standard Checkbox Images Checkbox Formula Field in Visualforce →

Comments

  1. Jeremy Ross says

    May 18, 2009 at 11:11

    I prefer to keep triggers very lean and free of business logic. I’d probably disagree with commenting your class with which triggers call it, for a few reasons. 1) The class shouldn’t know or care who calls it – the beauty of reuse, 2) someone will inevitably create a new client of the class and not update the “users” comment in the class, 3) this is related to 2, which is you’ll have a false sense of security of who is using the class.

    The “show dependencies” button on the apex class screen would be infinitely more useful if it would show dependents instead of dependencies.

    Reply
  2. Scott Hemmeter says

    May 18, 2009 at 14:11

    I use this approach with a slight mod.

    I have 1 trigger for each object and it fires for all events where I have code. Example of my Leads trigger below. It’s basically what you are suggesting, but it’s one common trigger and I add if/thens based upon the event that is firing.

    This way there is 1 trigger and 1 class for each object.

    trigger Leads on Lead (after insert, after update) {

    // AFTER INSERT
    if(Trigger.isAfter && Trigger.isInsert){
    Leads l = new Leads();
    l.CreateCampaignMembers(Trigger.new);
    }

    // AFTER UPDATE
    if(Trigger.isAfter && Trigger.isUpdate){
    Leads l = new Leads();
    l.setOpportunityDefaults(Trigger.new, Trigger.oldMap);
    l.transferOpptyFromLeadToAccount(Trigger.new, Trigger.oldMap);
    }

    }

    Reply
    • David Schach says

      May 18, 2009 at 14:37

      I was just thinking about something similar today – with some logic and passing a String parameter, one could use the same class to update a single field to multiple values. For instance, an opportunity trigger to Account.Type -> Customer if total won opp value is >0, and -> VIP Customer if total won opp value > 250,000.
      The possibilities are limitless!

      Reply
  3. Dave Manelski says

    May 18, 2009 at 19:40

    We have a few classes with methods used by multiple triggers. In lieu of passing the trigger set (sObjects), we’ve opted for passing primivitive data types only between triggers and classes, purposefully to reduce dependencies. In your example, I would probably opt for passing a list of strings (for the Ids in the trigger set) and perform a SOQL in the class.

    By keeping these dependencies to a minimum, you can easier package code, among other benefits. I’ve adopted this “best practice” based on observation and advice of more talented coders than myself so I’d be curious to find out how someone with formal computer science training weighs in on this.

    Reply
  4. Jeff Douglas says

    May 22, 2009 at 15:21

    David, thanks for taking my crappy code and making it better. I won’t receive a bill will I? I find your reasoning sound and have been refactoring a number of triggers in this same way.

    Reply

Trackbacks

  1. Auto-convert Contact-matching Leads : X-Squared On-Demand says:
    February 11, 2010 at 10:23

    […] the trigger. Note that I followed my own advice from Pulling Code Out of Triggers. (Other trigger classes have been […]

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Find Us Online

  • Twitter
  • Facebook
  • LinkedIn
  • RSS

Subscribe

RSS Feed Comments

Subscribe via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 5,089 other subscribers

Copyright © 2008–2022 X-Squared On Demand · Genesis Framework by StudioPress · WordPress · Log in