All Logic in the Trigger Body (No Handler Class)
“Wrote 300 lines of logic directly in the trigger. Six months later, nobody could maintain it. Including me.”
What Happened
My first big Apex trigger for a Cloud Nimbus client had all the business logic right in the trigger body. Before insert, after insert, before update, after update — all crammed into one file with nested if-else blocks. It worked. Then the client needed changes. Then more changes. Six months later the trigger was 300 lines of spaghetti and I couldn't tell where one operation ended and another began. I had to rewrite the entire thing using a handler pattern.
The Wrong Way
trigger OpportunityTrigger on Opportunity (
before insert, after insert,
before update, after update
) {
if (Trigger.isBefore && Trigger.isInsert) {
for (Opportunity o : Trigger.new) {
if (o.Amount > 100000) {
o.Priority__c = 'High';
if (o.StageName == 'Closed Won') {
// 50 more lines of logic here...
}
}
}
}
if (Trigger.isAfter && Trigger.isInsert) {
// Another 100 lines...
}
// This goes on forever. Untestable. Unmaintainable.
}The Right Way
// Trigger: thin dispatcher only
trigger OpportunityTrigger on Opportunity (
before insert, after insert,
before update, after update
) {
OpportunityTriggerHandler handler =
new OpportunityTriggerHandler();
handler.run();
}
// Handler: organized, testable, maintainable
public class OpportunityTriggerHandler
extends TriggerHandler {
public override void beforeInsert() {
setPriority();
}
public override void afterInsert() {
notifyTeam();
}
private void setPriority() {
for (Opportunity o : (List<Opportunity>)
Trigger.new) {
if (o.Amount > 100000)
o.Priority__c = 'High';
}
}
}The Lesson
Triggers should be one line: call the handler. All logic belongs in handler classes. If you can't unit test a method independently, your architecture is wrong.
Enjoyed this? Get more like it.
Glen's Musings — AI, investing, and building things. Occasional. Free.
More Apex Mistakes
SOQL Query Inside a For Loop (The Classic)
Wrote a SOQL query inside a for loop. 200 records came in. 200 queries fired. Governor said no.
Read morePainfulTest Class That Only Tests One Record
Wrote a test class that inserted 1 record. Got 100% coverage. Deployed. Trigger failed on bulk operations.
Read moreAnnoyingMixed DML: Setup and Non-Setup Objects in the Same Transaction
Inserted a User and an Account in the same transaction. Salesforce said absolutely not.
Read more