I have 4 very similar code blocks in a trigger that deal with synchronizing record type changes from Opportunity to its children. The only difference between them is that they do work on different custom objects. Since the actual work they do is identical, it seems like I should be able to combine them using a generic object type but I'm a little fuzzy on how to do it (assuming I even should).
(Note: I'm interested in general best practice here, not how to refactor specific code. Links are acceptable!)
My repetitive code looks something like this:
trigger OpportunityTrigger on Opportunity (before insert, after insert, before update, after update, before delete, after delete) {
if (Trigger.isAfter && Trigger.isUpdate) {
// Get record type map
List<String, Id> rtMap = OpportunityHelper.getRecordTypeMap();
// Update lists
List<Custom_Object1__c> obj1Updates = new List<Custom_Object1__c>();
List<Custom_Object2__c> obj2Updates = new List<Custom_Object1__c>();
// Get object 1 records
List<Custom_Object1__c> obj1List = [
SELECT
Id,
Opportunity__c,
RecordTypeId
FROM Custom_Object1__c
WHERE Opportunity__c IN : Trigger.newMap.keyset()
];
// Get object 2 records
List<Custom_Object2__c> obj2List = [
SELECT
Id,
Opportunity__c,
RecordTypeId
FROM Custom_Object2__c
WHERE Opportunity__c IN : Trigger.newMap.keyset()
];
// Map to opportunities
Map<Id, List<Custom_Object1__c>> oppId2Obj1Map = OpportunityHelper.mapify(obj1List);
Map<Id, List<Custom_Object2__c>> oppId2Obj2Map = OpportunityHelper.mapify(obj2List);
for (Opportunity o : Trigger.new) {
// Get record type of opportunity
String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
// Get opportunity children
List<Custom_Object1__c> obj1List = oppId2Obj1Map.get(o.Id);
List<Custom_Object2__c> obj2List = oppId2Obj2Map.get(o.Id);
// Sync up obj1 record types
for (Custom_Object1__c obj1 : obj1List) {
// Get record type names of child
String rtObj1 = OpportunityHelper.getRecordTypeName(obj1.RecordTypeId);
// If record types don't match, change the record type of obj1
if (rtOpportunity <> rtObj1) {
obj1.RecordTypeId = rtMap.get(rtOpportunity);
obj1Updates.add(obj1);
}
}
// Sync up obj2 record types
for (Custom_Object2__c obj2 : obj2List) {
// Get record type names of child
String rtObj2 = OpportunityHelper.getRecordTypeName(obj2.RecordTypeId);
// If record types don't match, change the record type of obj2
if (rtOpportunity <> rtObj2) {
obj2.RecordTypeId = rtMap.get(rtOpportunity);
obj2Updates.add(obj2);
}
}
}
// Process record type changes
if (obj1Updates.size() > 0) update obj1Updates;
if (obj2Updates.size() > 0) update obj2Updates;
}
}
So...is there some way I can use a generic object type to minimize my repetitive code here? Maybe a function prototype I can pass the object name into?
Something more like...
...
List<sObject> stuffToUpdate1 = newList<sObject>();
List<sObject> stuffToUpdate2 = newList<sObject>();
for (Opportunity o : Trigger.new) {
stuffToUpdate1.add(syncRecordTypes('Custom_Object1__c', o));
stuffToUpdate2.add(syncRecordTypes('Custom_Object2__c', o));
}
if (stuffToUpdate1.size() > 0) update stuffToUpdate1;
if (stuffToUpdate2.size() > 0) update stuffToUpdate2;
...
private static List<Object> syncRecordTypes(String sObjName, Opportunity opp) {
// ???
}