Review and Refactor
By the end of this lesson, you'll be able to:
- Review the complete feature across trigger, handler, and service class
- Identify any remaining duplication or unclear naming
- Confirm the final structure matches Module 24's trigger framework and Module 14's clean-code habits
Prerequisites: "Test the Feature"
The finished feature, end to end
trigger OpportunityTrigger on Opportunity (before update, after update) {
OpportunityTriggerHandler handler = new OpportunityTriggerHandler();
if (Trigger.isBefore) {
handler.beforeUpdate(Trigger.new, Trigger.oldMap);
}
if (Trigger.isAfter) {
handler.afterUpdate(Trigger.new, Trigger.oldMap);
}
}
Three pieces, each with one clear job: OpportunityTrigger (routes events), OpportunityTriggerHandler (detects what changed and by how much), AccountRollupService (applies the adjustment). This mirrors every project module's closing lesson — a system that works, then reviewed once more with fresh eyes.
Checking against this course's standards
- Bulk-safe? Yes — exactly one query and one DML statement in the rollup path, regardless of batch size (Module 25).
- Thin trigger? Yes — the trigger body only routes to handler methods (Module 24).
- Single Responsibility? Yes — three classes, three distinct jobs (Module 14).
- Validated? Yes — a Closed Won Opportunity can't save without a positive Amount (this module, Lesson 4).
- Verified? Yes, manually — formal automated tests are still ahead, in Module 31.
One more refactor: a shared constant
public class OpportunityTriggerHandler {
private static final String CLOSED_WON = 'Closed Won';
public void afterUpdate(List<Opportunity> newOpportunities, Map<Id, Opportunity> oldMap) {
for (Opportunity opp : newOpportunities) {
Opportunity oldOpp = oldMap.get(opp.Id);
Boolean justWon = opp.StageName == CLOSED_WON && oldOpp.StageName != CLOSED_WON;
// ...
}
}
}
The literal string 'Closed Won' appears in three separate places across this module's code so far — a classic candidate for Module 13's final keyword: one named constant, changed in exactly one place if the stage name ever needs to change, instead of hunting down every copy.
Exercise
Refactor this method to use a private static final String constant named MINIMUM_AMOUNT_ERROR instead of the repeated literal message.
Show hint
private static final String MINIMUM_AMOUNT_ERROR = '...';
Review and Refactor Quiz
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 final lesson steps back and reviews the whole feature — trigger, handler, and service class together — checking it against everything this course has taught about clean, bulk-safe, well-structured Apex.