Concepts


FEA Pattern


FEA is an apex trigger helper design pattern created specifically to provide some decent level of resource management as well as boudaries to programmers so that apex code is as optimized as it gets.

For a Salesforce org having thouthands of lines of apex code oriented to sobject automations via apex triggers, things can get out of control and most of the time they are.

So after spending a lot of time writing apex code for triggers and without having a decent apex trigger framework it is obvious the need of organizing and improving apex helpers if there is no hope of implementing the so much mention apex trigger framework.

FEA stands for:

Consider the following apex trigger which does not implement any sort of apex trigger framework rather just executes apex helpers directly:



        trigger ATARCOpportunityTrigger on Opportunity (before insert, before update, before delete, after insert, after update, after delete, after undelete) {

        for(Opportunity record : trigger.new){
            OpptyAssitantHelper.Filter( trigger.oldmap ,record, trigger.isinsert);
        }

        OpptyAssitantHelper.Execute();

        for(Opportunity record : trigger.new){
            OpptyAssitantHelper.Action( trigger.oldmap ,record, trigger.isinsert);
        }


        }

    

We can break down the previous code in three stages:

  • First, the apex helper have to identify which records to work with so it must filter specific records meeting the criteria with OpptyScoreCalcHelper.Filter, like updated opportunities where TotalAmount field has less value. But the for loop is actually outside of the OpptyScoreCalcHelper.Filter method, which reduces the need of doing a for loopp within it, therefore if any additional apex helper does this way it means we can potentially have ONE for loop iteration shared across all the helpers. AWESOME!
  • Second, after identifying records meeting the criteria, it must do someting with them, an operation like looking for more data in other sobjects, so now it must execute such operation with OpptyScoreCalcHelper.Execute method.

    This time a bunch of different statements could be running inside the execute method, but it must only be executed if at least 1 record is gathered by the filter method.

    Following the previous thought in the first stage, it could mean that some opportunity products were potentially removed thus this is why the TotalAmount went down, then we can setup something in the execute method to look for their related accounts and create additional tasks to the opportunity team so that we pay more attention to this particular opportunity and they can even try gain back those opportunity products discarded by the customer.

  • Third, we might mark those opportunities which has been identified in the first stage and created some follow up tasks in the second stage, OpptyAssitantHelper.Action focus on single record field updates. For example here we could set some PendingFollowUpAction__c to true for those particular opportunities.

It could seem like it is a lot of wasted time reading this, but trust me every millisecond you can save in your apex trigger transactions it means you are less likely to reach cpu governor limit

So depending on how many apex helpers you are to execute it will start making sense, to proof this point, let's continue adding more apex helper to run from the apex trigger as example:



        trigger ATARCOpportunityTrigger on Opportunity (before insert, before update, before delete, after insert, after update, after delete, after undelete) {

        for(Opportunity record : trigger.new){
            OpptyAssitantHelper.Filter( trigger.oldmap ,record, trigger.isinsert);
            OpptyReachHelper.Filter( trigger.oldmap ,record, trigger.isinsert);
            OpptyEngagementHelper.Filter( trigger.oldmap ,record, trigger.isinsert);
            OpptyClousureHelper.Filter( trigger.oldmap ,record, trigger.isinsert);
            OpptyTrackerHelper.Filter( trigger.oldmap ,record, trigger.isinsert);
            OpptyValidationsHelper.Filter( trigger.oldmap ,record, trigger.isinsert);
            OpptyLoyaltyHelper.Filter( trigger.oldmap ,record, trigger.isinsert);
            OpptyOnboardingHelper.Filter( trigger.oldmap ,record, trigger.isinsert);
            OpptySocialHelper.Filter( trigger.oldmap ,record, trigger.isinsert);
            OpptyIntegrationHelper.Filter( trigger.oldmap ,record, trigger.isinsert);
        }

        OpptyAssitantHelper.Execute();
        OpptyReachHelper.Execute();
        OpptyEngagementHelper.Execute();
        OpptyClousureHelper.Execute();
        OpptyTrackerHelper.Execute();
        OpptyValidationsHelper.Execute();
        OpptyLoyaltyHelper.Execute();
        OpptyOnboardingHelper.Execute();
        OpptySocialHelper.Execute();
        OpptyIntegrationHelper.Execute();

        for(Opportunity record : trigger.new){
            OpptyAssitantHelper.Action( trigger.oldmap ,record, trigger.isinsert);
            OpptyReachHelper.Action( trigger.oldmap ,record, trigger.isinsert);
            OpptyEngagementHelper.Action( trigger.oldmap ,record, trigger.isinsert);
            OpptyClousureHelper.Action( trigger.oldmap ,record, trigger.isinsert);
            OpptyTrackerHelper.Action( trigger.oldmap ,record, trigger.isinsert);
            OpptyValidationsHelper.Action( trigger.oldmap ,record, trigger.isinsert);
            OpptyLoyaltyHelper.Action( trigger.oldmap ,record, trigger.isinsert);
            OpptyOnboardingHelper.Action( trigger.oldmap ,record, trigger.isinsert);
            OpptySocialHelper.Action( trigger.oldmap ,record, trigger.isinsert);
            OpptyIntegrationHelper.Action( trigger.oldmap ,record, trigger.isinsert);
        }


        }

    

Looking at the previous code we can say that the first loop is running for all the apex helper's Filter method inside it, 10 to be precise. So if each filter method has its own for loop that's 10 for loop running instead of only 1 we are currently seeing.

We can say the exact same comment regarding the last for loop, so instead of 10 for loop running for the Action method 1 per helper, we are saving 9 and just running 1 for loop.

Overall we are saving 18 for loops if we keep this thinking, this is a huge win in favor of our code performance, this is what FEA is all about.