Advanced 35 min read

Build the Selector Layer

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

  • Write selector classes for Project__c and Milestone__c following Module 43's pattern
  • Design a selector method that supports the health-recalculation use case specifically
  • Apply WITH SECURITY_ENFORCED consistently across every selector

Prerequisites: "Build the Domain Layer"

ProjectSelector and MilestoneSelector

public with sharing class ProjectSelector {
    public Map<Id, Project__c> selectByIdAsMap(Set<Id> ids) {
        return new Map<Id, Project__c>([
            SELECT Id, Health__c, Status__c FROM Project__c WHERE Id IN :ids WITH SECURITY_ENFORCED
        ]);
    }
}

public with sharing class MilestoneSelector {
    public List<Milestone__c> selectByProjectIds(Set<Id> projectIds) {
        return [
            SELECT Id, Project__c, Status__c, Due_Date__c
            FROM Milestone__c
            WHERE Project__c IN :projectIds
            WITH SECURITY_ENFORCED
        ];
    }
}

Both follow Module 43\'s exact shape — one class per object, WITH SECURITY_ENFORCED on every query, methods named for what they select rather than exposing raw SOQL to callers.

A selector method shaped by its actual use case

selectByProjectIds exists specifically because MilestoneStatusService.recalculateProjectHealth (Lesson 5) needs every Milestone belonging to a given set of Projects, to determine whether any are overdue. The selector\'s method signature is designed around this concrete need, rather than being a generic "get everything" method — a deliberate, requirements-driven API, echoing Lesson 1\'s "requirements imply architecture" theme.

Consistency across every selector in the project

Every selector class in this project — for Project__c, Milestone__c, and the Support_Case__c/Time_Entry__c selectors built alongside them — applies WITH SECURITY_ENFORCED the same way, ensuring Module 28\'s security discipline is enforced uniformly across a data model spanning three departments, not just remembered in some places and forgotten in others.

Exercise

As a comment, explain why MilestoneSelector.selectByProjectIds takes a Set<Id> of Project IDs rather than a single Project Id.

Show hint

Think about how many projects a health-recalculation job might process in one run.

APEX

Build the Selector Layer Quiz

1. Why does every selector class in this project apply WITH SECURITY_ENFORCED the same way?

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

Two selector classes centralize every query this project needs against Project__c and Milestone__c — Module 43's exact selector pattern, applied to a data model with more inter-object relationships than the banking system had.