Salesforce — Partitioned Trigger Handler Pattern

Existing Trigger Handler patterns

public class AccountTriggeHandler implements ITriggerHandler {    public void handleBeforeInsert() {
// ...
}
public void handleBeforeUpdate() {
// ...
}
// other trigger-handler methods ...}

Issues with Trigger Handlers

  • Difficulty to trace all trigger functionality, as it is spread across various classes which are not necessarily grouped in any way
  • The TriggerHandler will still need to keep a lot of code to maintain the structure, do some basic pre-filtering/grouping, call the other classes, etc.

Partitioned Trigger Handler

  • Separate Trigger-code by functionality blocks into dedicated classes — “Trigger partitions”
  • Minimise size of Trigger Handler to allow easier management of partitions (adding, removing, re-order)
Class diagram for the Partitioned Trigger Handler

Virtual class PartitionedTriggerHandler

Class <Object>TriggerHandler

Interface ITriggerHandlerPartition

  • getOperations() — returns a list of Trigger operations on which this partition should be executed (e.g. before-insert, after-update, etc.)
  • initialIteration(SObject newRecord, SObject oldRecord) — this method will be called for each record of the trigger, at the beginning of the trigger handler; it can be used e.g. for initial data gathering from the records
  • main() — this method can contain the main functionality of the partition, which is called (only once) after the initialIteration; e.g. it can be used for needed SOQL queries
  • finalIteration(SObject newRecord, SObject oldRecord) — this method will be called for each record of the trigger, at the end of the trigger handler (after the main-method); it can be used for e.g. making changes to the records based on calculations done in the main-method

Class <Object>_TP_<Name>

Example implementation

public class Opportunity_TP_AccountType 
implements ITriggerHandlerPartition {
Set<Id> accountIds = new Set<Id>();
Map<Id, Account> accountMap;
public System.TriggerOperation[] getOperations() {
return new System.TriggerOperation[] {
System.TriggerOperation.BEFORE_INSERT
};
}
public void initialIteration(SObject newRecord,
SObject oldRecord) {
Opportunity opp = (Opportunity) newRecord;
this.accountIds.add(opp.AccountId);
}
public void main() {
this.accountMap = new Map<Id, Account>([
SELECT Type FROM Account
WHERE Id IN :this.accountIds
]);
}
public void finalIteration(SObject newRecord,
SObject oldRecord) {
Opportunity opp = (Opportunity) newRecord;
opp.Account_Type__c =
this.accountMap.get(opp.AccountId).Type;
}
}
public class Account_UpdateOpportunityAccountType 
implements ITriggerHandlerPartition {
Set<Id> accountIdsWithChangedType = new Set<Id>();
public System.TriggerOperation[] getOperations() {
return new System.TriggerOperation[] {
System.TriggerOperation.AFTER_UPDATE
};
}
public void initialIteration(SObject newRecord,
SObject oldRecord) {
Account acc = (Account) newRecord;
Account oldAcc = (Account) oldRecord;

if (acc.Type != oldAcc.Type) {
accountIdsWithChangedType.add(acc.Id);
}
}
public void main() {
if (accountIdsWithChangedType.size() > 0) {
Opportunity[] relatedOpps = [
SELECT AccountId FROM Opportunity
WHERE AccountId IN :accountIdsWithChangedType
];
for (Opportunity opp : relatedOpps) {
Account acc =
(Account) Trigger.newMap.get(opp.AccountId);
opp.Account_Type__c = acc.Type;
}

udpate relatedOpps;
}
}
public void finalIteration(SObject newRecord,
SObject oldRecord) {
}
}

Potential drawbacks

Conclusion

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Counting with Java generics

Enable faster uploads and downloads with your S3 Bucket

Google Anthos

Microsoft Azure Interview Questions And Answers

Relative Sizing — User Story Estimation

What’s behind a dynamic search field?

Python Algorithm Pt.7: Nodes

Google’s New Fuchsia OS: Download And Build From Source Code

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Josip Jurić

Josip Jurić

More from Medium

What I did to pass Salesforce B2C Commerce Architect Certification Exam

Steps to create LWC Component

Rendering an ISML Template in SFRA (Salesforce Commerce Cloud)

Skills and Resources required to implement a Salesforce/SAP Integration

Skills required to integrate Salesforce with SAP