1

In a BeforeUpdate trigger of a custom object, I am checking to see what custom fields have been updated and based on the updates, want to call specific methods that use the updated fields to run some processes. Let's say update to field1 requires running method1 and method3 and update to field2 requires running method2 and method4. I want to make sure that I can check if field1 and/or field2 are changed and run the methods accordingly. What I'm doing right now is this:

list<sObject> field1Changed = new list<sObject>();  
list<sObject> field2Changed = new list<sObject>();

if(newObject.field1__c!=oldObject.field1__c){  
    field1Changed.add(newObject);
}

if(newObject.field2__c!=oldObject.field2__c){  
    field2Changed.add(newObject);

}

if(field1Changed.size()>0){   
    field1Changed = method1(field1Changed);   
    field1Changed = method3(field1Changed);         
}

if(field2Changed.size()>0){  
    field2Changed = method2(field2Changed);   
    field2Changed = method4(field2Changed);   
}
  1. How can I do this more efficiently? bearing in mind that this is in a trigger and can be called thousands of times a day.

  2. How can I build a more scalable solution knowing that I have 15 fields and 10 methods that I need to call based on similar criteria and that of those fields 12 fields are very rarely updated.

  3. Given that I'm creating two separate collections for each field, if both fields get updated, would running methods 2,4 overwrite the results of the methods 1,3?

P.S: Methods mostly update other fields based on the updated fields using simple math/logic by iterating through each record. For example, method1 is something like:

if(newRecord.field5__c){
    trade.field3__c = math.abs(trade.field1__c);
    trade.field4__c = -1* math.abs(trade.field2__c);
 }else{
    trade.field3__c = -1* math.abs(trade.field1__c);
    trade.field4__c = math.abs(trade.field2__c);
 }

Other methods may contain a SOQL query to another object to update other fields similarly.

  • You haven't actually defined any methods here. Your post only includes pseudo-code. – Adrian Larson Jul 27 '16 at 21:23
  • The methods update other fields based on these fields. I can add more details if it helps. What is important to know about the methods? – Jorjani Jul 27 '16 at 21:24
  • If you apply both methods to the same record, latest execution wins. – Adrian Larson Jul 27 '16 at 21:43
  • Are the records not passed by reference? I was expecting that when I pass by reference the updates from the previous method should be passed to the second as well – Jorjani Jul 28 '16 at 20:39
2

Just a wrapping of Adrian's answer in code that avoids lots of list declarations (but only works if the logic is always related to just one field):

for (SObjectField f : new SObjectField[] {
        YourObject__c.Field1__c,
        YourObject__c.Field2__c,
        ...
        }) {
    SObject[] matches = Select.Field.hasChanged(f).filter(newRecords, oldMap);
    if (f == YourObject__c.Field1__c) {
        method1(matches);
        method3(matches); 
    } else if (f == YourObject__c.Field2__c) {
        method1(matches);
        method3(matches);
    } else ...
}

Now an if/else if/else chain is never a thing of beauty or speed but if your methods are doing significant work its not going to matter.

Not sure why you are returning the lists from the methods unless you are doing something relatively unusual in the methods.

| improve this answer | |
2

Take a look at the Selector library. It might not be more efficient in terms of execution, but it sure is in terms of writing the code.

List<SObject> recordsYouCareAbout = Select.Field.hasChanged(YourObject__c.Field__c)
    .filter(newRecords, oldMap);

You can also do combinations:

Select.Filter hasField1Changed = Select.Field.hasChanged(YourObject__c.Field1__c);
Select.Filter hasField2Changed = Select.Field.hasChanged(YourObject__c.Field1__c);
List<SObject> recordsYouCareAbout = Select.Records.both(hasField1Changed, hasField2Changed)
    .filter(newRecords, oldMap);

It's one option. I favor it, but then my former colleagues developed it and I really like the API. So I'm biased.

One of my favorite aspects is that this library makes Separation Of Concerns much easier to implement. You can write action methods that only accept List<SObject> filterResults and make them completely independent from the filtering logic.

| improve this answer | |
  • That looks interesting. It looks like it will save some coding time! I just added a third question. Can you see if you can respond to that too please? – Jorjani Jul 27 '16 at 21:23
  • So, filters and actions should be very separate methods (which this library will help with). You only outlined the filters in your post, and not the actions. @DavidJ – Adrian Larson Jul 27 '16 at 21:27
  • I added an example to the method. This is a beforeupdate trigger so the actions are very preliminary. We have a similar situation with afterUpdate trigger as well. – Jorjani Jul 27 '16 at 21:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.