Apex Trigger Design Pattern – Convert Trigger to Helper Class and Trigger

Apex Trigger Design Pattern

Apex Trigger

Apex triggers enable developers or administrators perform custom actions before or after events to records in Salesforce, such as insertions, updates, or deletions.

A trigger can be used to perform operations based on specific conditions like modifying related records or restricting certain operations from happening. It can be used to do anything you can do in Apex, including executing SOQL and DML or calling custom Apex methods.

Use triggers to perform tasks that can’t be done by using the point-and-click tools in the Salesforce user interface.

Triggers can be defined for top-level standard objects, such as Account or Contact, custom objects, and some standard child objects. They are active by default when created. Salesforce automatically fires active triggers when the specified database events occur.

Trigger Design Pattern

In Salesforce, one of the widely-recognized best practice is to make Triggers logic-less. That is to keep the Trigger free from the business logic and put the logic code into Trigger handler/helper class. This means the role of the Trigger is to delegate the logic responsibilities to some other handler class.

In this post, I separated the Trigger named AdddRelatedRecords on Trailhead into a trigger and a handler class for the trigger to delegate to it. Below is the trigger code:

trigger AddRelatedRecord on Account(after insert, after update) {
    List<Opportunity> oppList = new List<Opportunity>();
    
    // Get the related opportunities for the accounts in this trigger
    Map<Id,Account> acctsWithOpps = new Map<Id,Account>(
        [SELECT Id,(SELECT Id FROM Opportunities) FROM Account WHERE Id IN :Trigger.New]);
    
    // Add an opportunity for each account if it doesn't already have one.
    // Iterate through each account.
    for(Account a : Trigger.New) {
        System.debug('acctsWithOpps.get(a.Id).Opportunities.size()=' + acctsWithOpps.get(a.Id).Opportunities.size());
        // Check if the account already has a related opportunity.
        if (acctsWithOpps.get(a.Id).Opportunities.size() == 0) {
            // If it doesn't, add a default opportunity
            oppList.add(new Opportunity(Name=a.Name + ' Opportunity',
                                       StageName='Prospecting',
                                       CloseDate=System.today().addMonths(1),
                                       AccountId=a.Id));
        }           
    }
    if (oppList.size() > 0) {
        insert oppList;
    }
}

I created the helper class with all the logic from the trigger and called it AddRelatedRecord. I used global access modifier because it is more permissive than the public modifier and allows access across namespaces and applications.

The helper class

global class AddRelatedRecord {
    
public static void  addingRelatedRecord (List<Account> accts) {
 List<Opportunity> oppList = new List<Opportunity>();
    
    // Get the related opportunities for the accounts in this trigger
    Map<Id,Account> acctsWithOpps = new Map<Id,Account>(
        [SELECT Id, (SELECT Id FROM Opportunities) FROM Account WHERE Id IN :accts]);
    
    // Add an opportunity for each account if it doesn't already have one.
    // Iterate through each account.
    for(Account a : accts) {
        System.debug('acctsWithOpps.get(a.Id).Opportunities.size()=' + acctsWithOpps.get(a.Id).Opportunities.size());
        // Check if the account already has a related opportunity.
        if (acctsWithOpps.get(a.Id).Opportunities.size() == 0) {
            // If it doesn't, add a default opportunity
            oppList.add(new Opportunity(Name=a.Name + ' Opportunity',
                                       StageName='Prospecting',
                                       CloseDate=System.today().addMonths(1),
                                       AccountId=a.Id));
        }           
    }

    if (oppList.size() > 0) {
        insert oppList;
    }
}
}

One of the benefits of Apex classes is code reuse which means that class methods can be called by triggers and other classes.

The trigger named AddRelatedRecordTrigger  with the context variable is written below:

trigger AddRelatedRecordTrigger on Account (after insert, after update) {
 AddRelatedRecord.addingRelatedRecord(Trigger.new);
}

 

 

This Post Has One Comment

  1. amit singh

    Hii plz solve this trigger …..
    Create a junction object named ‘Job Application’ between two objects named ‘Position’ and ‘Candidate’.The position and candidate has many to many relationships which will be established due to the junction object. Create a status field of type picklist on both position and candidate. If the status on a candidate record is updated to ‘Approved’, the status field on position should be updated to ‘Approved’ only if status on all related candidates have been updated to ‘Approved’.

Comments are closed.