Question
I am relatively new to Salesforce development and have been exploring different design patterns to write efficient and maintainable code. In my current structure, I have a trigger, a handler class, and a service class that processes records. Each service method iterates over the same set of records for different operations. As the number of methods grows, I find myself looping through the same records multiple times, which seems inefficient. Here’s an example of my structure:
TriggSer
trigger OpportunityTrigger on Opportunity (before insert, before update, after insert, after update) {
SObjectTriggerHandler.run(new OpportunityBO());
}
Handler
public with sharing class OpportunityBO extends SObjectTriggerHandler {
private List<Opportunity> opportunities;
public OpportunityBO() {
super();
this.opportunities = super.newList;
}
@Override
protected void onBeforeInsert() {
new OpportunityService(this.opportunities).method1().method2().method3();
}
@Override
protected void onAfterUpdate() {
new OpportunityService(this.opportunities).method4();
}
}
Service
public with sharing class OpportunityService {
private List<Opportunity> opportunities;
public OpportunityService(List<Opportunity> opps) {
this.opportunities = opps;
}
public OpportunityService method1() {
for (Opportunity opp : opportunities) {
// Some logic
}
return this;
}
public OpportunityService method2() {
for (Opportunity opp : opportunities) {
// Some logic
}
return this;
}
public OpportunityService method3() {
for (Opportunity opp : opportunities) {
// Some logic
}
return this;
}
public OpportunityService method4() {
for (Opportunity opp : opportunities) {
// Some logic
}
return this;
}
}
I want to avoid excessive looping and improve the overall efficiency of my code. What are some strategies or design patterns I can use to achieve this?
Answer
The short answer is that excessive looping in itself is rarely a problem until it becomes a performance bottleneck. Focus on making your code readable, testable, and compliant with governor limits. Here are several strategies and considerations:
1. Consolidate Logic in a Single Loop
Instead of having separate loops in different service methods, consolidate the logic into a single loop. This avoids iterating over the same records multiple times.
public OpportunityService processRecords() {
for (Opportunity opp : opportunities) {
if (someCondition) {
// Logic from method1
}
if (anotherCondition) {
// Logic from method2
}
// Additional logic from other methods
}
return this;
}
In your handler, call processRecords
instead of chaining multiple methods.
2. Use Map-Based Processing
If your logic is based on specific criteria, consider using a Map
to group or organize records before processing. This reduces redundant checks and loops.
public OpportunityService groupAndProcess() {
Map<String, List<Opportunity>> groupedRecords = new Map<String, List<Opportunity>>();
for (Opportunity opp : opportunities) {
String key = getGroupKey(opp);
if (!groupedRecords.containsKey(key)) {
groupedRecords.put(key, new List<Opportunity>());
}
groupedRecords.get(key).add(opp);
}
for (String key : groupedRecords.keySet()) {
List<Opportunity> group = groupedRecords.get(key);
// Process each group
}
return this;
}
private String getGroupKey(Opportunity opp) {
// Logic to determine the grouping key
return opp.StageName;
}
3. Don’t Optimize Prematurely
The Salesforce governor limits are designed to ensure efficient code execution. Benchmarking shows that looping is not inherently expensive. For example:
- A bare loop iterating over 10,000 records uses ~5 CPU time units.
- A loop processing 10,000 SObjects uses ~25 CPU time units.
- Salesforce provides 39,000 CPU time units per synchronous transaction.
Focus on avoiding expensive operations like SOQL and DML within loops rather than worrying about the loops themselves.
4. Measure and Profile
Before refactoring for performance, measure the actual CPU time usage to confirm that looping is the issue. You can use simple benchmarks to understand where the bottlenecks are:
Long startTime = Limits.getCpuTime();
for (Opportunity opp : opportunities) {
// Logic here
}
Long endTime = Limits.getCpuTime();
System.debug('CPU Time: ' + (endTime - startTime));
While consolidating logic and using maps can reduce redundant looping, avoid over-optimizing without evidence of performance issues. Prioritize readability, testability, and proper use of governor limits. When performance does become a concern, measure and refine based on actual data.
Real-Time Project-Based Salesforce Course to Kick Start Your Career
Our Salesforce Course is thoughtfully designed to offer a deep understanding of the Salesforce platform, equipping you with the necessary skills to thrive in the CRM industry. The program covers essential modules like Salesforce Admin, Developer, and AI, seamlessly combining foundational knowledge with hands-on experience. By working on practical projects and real-life assignments, you’ll develop the expertise to tackle intricate business challenges using Salesforce solutions. Our skilled instructors ensure you gain both technical expertise and industry-specific insights to excel in the Salesforce ecosystem.
In addition to mastering technical concepts, our Salesforce training in Pune provides personalized coaching, exam preparation, and interview guidance to enhance your career opportunities. You will have access to a range of study materials, practical project experience, and one-on-one support throughout your learning journey. By the end of the course, you’ll be fully prepared for certification exams and equipped with the real-world problem-solving skills employers highly value. Begin your Salesforce career with us and explore limitless career possibilities. Register for a Free Demo today!
Leave a Reply
You must be logged in to post a comment.