Skip to main content

Code reviews rule: Business logic in triggers

Written by David Martin
Updated this week

Business logic in triggers

Why is this an issue?

Embedding business logic directly inside a trigger leads to several problems:

  • Untestable in isolation: Trigger code can only be exercised by performing DML operations, making unit testing difficult.

  • Not reusable: The same logic may be needed in other contexts but cannot be invoked independently.

  • Difficult to maintain: As triggers grow in complexity, they become harder to read, understand, and modify.

  • Poor separation of concerns: Mixing trigger plumbing with business rules violates clean architecture principles.

Examples

Example of incorrect code:

trigger AccountTrigger on Account (before insert) {
for (Account acc : Trigger.new) {
// Business logic directly in trigger
if (acc.Industry == 'Technology') {
acc.Priority__c = 'High';
acc.Segment__c = 'Enterprise';
}
// More complex logic...
}
}

Example of correct code:

// Trigger delegates to handler
trigger AccountTrigger on Account (before insert) {
AccountTriggerHandler.handleBeforeInsert(Trigger.new);
}

// Handler class contains logic
public class AccountTriggerHandler {
public static void handleBeforeInsert(List<Account> accounts) {
AccountService.setDefaults(accounts);
}
}

// Service class is testable and reusable
public class AccountService {
public static void setDefaults(List<Account> accounts) {
for (Account acc : accounts) {
if (acc.Industry == 'Technology') {
acc.Priority__c = 'High';
}
}
}
}

How can I fix violations?

  1. Create a trigger handler class: Move all logic out of the trigger and into a dedicated handler class.

  2. Create service classes: Extract business logic into reusable service classes that can be tested and called independently.

  3. Keep triggers minimal: Triggers should only delegate to handler methods without containing any logic themselves.

When should I disable this rule?

You may dismiss specific violations for very simple triggers that contain only trivial logic (e.g., setting a single default value).

Resources

Did this answer your question?