Advanced 25 min read

Review and Refactor

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

  • Review the complete feature across every module it draws on
  • Extract the routing-lookup construction into its own well-named private method if not already done
  • Confirm the final structure reflects every relevant course habit learned so far

Prerequisites: "Test the Feature"

The complete handler, assembled

public with sharing class CaseTriggerHandler {
    private static final String DEFAULT_QUEUE = 'General Support';

    public void beforeInsert(List<Case> newCases) {
        if (! hasRequiredFieldAccess()) {
            return;
        }

        Map<String, String> queueByPriorityAndType = buildRoutingLookup();

        for (Case c : newCases) {
            if (c.Priority == null || c.Type == null) {
                c.Assigned_Queue__c = DEFAULT_QUEUE;
                continue;
            }

            String key = c.Priority + '|' + c.Type;
            c.Assigned_Queue__c = queueByPriorityAndType.containsKey(key)
                ? queueByPriorityAndType.get(key)
                : DEFAULT_QUEUE;
        }
    }

    private Boolean hasRequiredFieldAccess() {
        return Schema.sObjectType.Case.fields.Priority.isAccessible()
            && Schema.sObjectType.Case.fields.Type.isAccessible();
    }

    private Map<String, String> buildRoutingLookup() {
        Map<String, String> lookup = new Map<String, String>();
        for (Case_Routing_Rule__mdt rule : [SELECT Priority__c, Case_Type__c, Queue_Name__c FROM Case_Routing_Rule__mdt]) {
            if (String.isBlank(rule.Priority__c) || String.isBlank(rule.Case_Type__c) || String.isBlank(rule.Queue_Name__c)) {
                continue;
            }
            lookup.put(rule.Priority__c + '|' + rule.Case_Type__c, rule.Queue_Name__c);
        }
        return lookup;
    }
}

Notice Module 6's ternary operator now replaces the earlier if/else fallback assignment — a small final polish, since the assignment is short and direct enough to read clearly either way.

The full checklist

  • Bulk-safe? One query total, regardless of batch size (Module 25).
  • Thin trigger, clean handler? Yes (Module 24).
  • Field-level security respected? Yes, checked before reading Priority/Type (Module 28).
  • Configurable without a deployment? Yes, via custom metadata (Module 29).
  • Sharing reasoned through deliberately? Yes, with sharing, with an explicit justification (this module).
  • Errors handled gracefully? Yes — missing data and malformed rules both degrade to a sensible fallback, never a crash (this module).
  • Manually verified? Yes, including the bulk-batch case (this module).
  • Named constants over magic strings? Yes, DEFAULT_QUEUE (Module 26's habit).

Why this checklist matters going forward

This isn't a one-off list specific to Case routing — it's the accumulated set of habits this course has built lesson by lesson, project by project, since Module 9. Running through a checklist like this at the end of any real feature — not just this course's projects — is exactly the discipline that separates code that merely works from code a team can trust in production.

Exercise

Rewrite this if/else fallback assignment as a single ternary expression, following this lesson's final polish.

Show hint

condition ? valueIfTrue : valueIfFalse

APEX

Review and Refactor Quiz

1. What is the purpose of running through a full review checklist at the end of a real feature?

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

The closing lesson steps back across the entire feature, checking it against every module it draws on — the most comprehensive review checklist of any project so far.