Advanced 15 min read

Separating Business Logic from Data Access

By the end of this lesson, you'll be able to:

  • Explain why mixing SOQL and business logic in the same method makes testing harder
  • Refactor a method to separate data access from logic

Prerequisites: The Selector Layer Pattern

The problem with mixing concerns

A method that queries Accounts and decides which ones are "at risk" and updates them is doing three different jobs at once — hard to unit test the "at risk" decision logic in isolation, since it's welded to a specific query and a specific DML statement.

Separating the concerns

Split into a selector (fetch the data), a pure logic method (decide, given data, what the outcome should be — no SOQL/DML at all), and a service (orchestrate: call the selector, call the logic, perform DML). The pure logic method becomes trivial to test with plain in-memory objects, no database needed.

Pure logic, separated from data access

public with sharing class AccountRiskService {
    public static Boolean isAtRisk(Account acc) {
        // Pure logic — no SOQL, no DML, easy to test with any Account instance
        return acc.AnnualRevenue < 10000 && acc.Industry == 'Retail';
    }

    public static void flagAtRiskAccounts(List<Account> accounts) {
        for (Account acc : accounts) {
            if (isAtRisk(acc)) {
                acc.Status__c = 'At Risk';
            }
        }
        update accounts;
    }
}

isAtRisk() can be tested with a plain new Account(...) in memory — no query needed — because it never touches the database itself.

Exercise

Extract the pure decision logic from this method into its own testable method: a Contact is a 'VIP' if TotalPurchases__c > 5000.

Show hint

The new method should take an sObject and return a Boolean, with no SOQL or DML inside it.

APEX

Separating Business Logic from Data Access — Quick Check

1. Why is a method that mixes SOQL, logic, and DML harder to test?

2. A pure logic method that takes an sObject and returns a Boolean can be tested without any SOQL query at all.

3. What are the three separated concerns in this pattern?

Log in to submit the quiz and save your score.

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

When a single method both queries data and applies business rules, testing the logic means always paying the cost of a real query too — separating data access (selector) from logic (service) makes each piece easier to read, test, and reuse independently.