Domain Layer and Trigger Handlers Revisited
By the end of this lesson, you'll be able to:
- Write a trigger handler class that centralizes an object's trigger dispatch logic
- Route Module 42's two separate Transaction__c triggers through a single handler
- Explain why a single handler per object is easier to reason about than several separate trigger files
Prerequisites: "Selector Layer"
The problem with two separate triggers on one object
Module 42 had both TransactionTrigger (after insert, balance updates) and TransactionValidation (before insert, validation) on the same Transaction__c object. This worked, but as an object accumulates more trigger logic over time, having several independent trigger files for the same object makes it hard to see, at a glance, everything that happens when a Transaction__c is inserted.
One handler, one entry point per event
public with sharing class TransactionTriggerHandler {
public void beforeInsert(List<Transaction__c> newTransactions) {
Set<Id> accountIds = new Set<Id>();
for (Transaction__c t : newTransactions) accountIds.add(t.Bank_Account__c);
Map<Id, Bank_Account__c> accounts = new BankAccountSelector().selectByIdAsMap(accountIds);
TransactionValidationService.validate(newTransactions, accounts);
}
public void afterInsert(List<Transaction__c> newTransactions) {
TransactionBalanceService.applyDeltas(newTransactions);
}
}
trigger TransactionTrigger on Transaction__c (before insert, after insert) {
TransactionTriggerHandler handler = new TransactionTriggerHandler();
if (Trigger.isBefore && Trigger.isInsert) handler.beforeInsert(Trigger.new);
if (Trigger.isAfter && Trigger.isInsert) handler.afterInsert(Trigger.new);
}
Now there is exactly one trigger file for Transaction__c, and exactly one handler class where every trigger event for that object is visible together — Lesson 3's TransactionValidationService and a new TransactionBalanceService (the balance-update logic from Module 42, similarly extracted) are both called from here.
Why one handler beats several independent trigger files
A developer asking "what happens when a Transaction__c is inserted?" now has exactly one file to open (TransactionTriggerHandler) rather than needing to know that logic is split across two separately-named trigger files that happen to both target the same object — a real cost that only shows up as an object accumulates more automation over time.
Exercise
As a comment, explain why the trigger itself (TransactionTrigger) contains almost no logic, delegating immediately to TransactionTriggerHandler.
Show hint
Think back to Lesson 2's separation-of-concerns framing of trigger mechanics as their own concern.
Domain Layer and Trigger Handlers Revisited Quiz
My Notes
Log in to keep private notes on this lesson.
Questions about this lesson
No questions yet — be the first to ask.
Log in to ask a question about this lesson.
Summary
A domain (trigger handler) class centralizes an object's trigger dispatch logic into one place — one class per object, with each trigger event routed to a clearly named method, rather than Module 42's two entirely separate trigger files for the same object.