Combining similar code with different objects












3















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) {
// ???
}









share|improve this question



























    3















    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) {
    // ???
    }









    share|improve this question

























      3












      3








      3








      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) {
      // ???
      }









      share|improve this question














      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) {
      // ???
      }






      apex trigger sobject bestpractice






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 11 at 20:50









      IxalmidaIxalmida

      1355




      1355






















          1 Answer
          1






          active

          oldest

          votes


















          6














          You can use Sobject get and put method to your advantage. This allows you to dynamically refer and set fiels in any Salesforce Record .



          I would go by adding all children in a Generic List, then iterate over it and assign new recordTypeId accordingly.



          So my code will be like:



          List<Sobject> genericChildList = new List<Sobject>();
          genericChildList.addAll(oppId2Obj1Map.get(o.Id)); //add child 1
          genericChildList.addAll(oppId2Obj2Map.get(o.Id)); //add child 2

          String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
          for(Sobject child : genericChildList){

          if(OpportunityHelper.getRecordTypeName(child.get('RecordTypeId')) != rtOpportunity ){
          child.put('RecordTypeId',rtMap.get(rtOpportunity));
          }

          }


          update genericChildList;





          share|improve this answer



















          • 1





            Thanks! I figured it would be something easy.

            – Ixalmida
            Jan 11 at 21:12











          Your Answer








          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "459"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f246391%2fcombining-similar-code-with-different-objects%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          6














          You can use Sobject get and put method to your advantage. This allows you to dynamically refer and set fiels in any Salesforce Record .



          I would go by adding all children in a Generic List, then iterate over it and assign new recordTypeId accordingly.



          So my code will be like:



          List<Sobject> genericChildList = new List<Sobject>();
          genericChildList.addAll(oppId2Obj1Map.get(o.Id)); //add child 1
          genericChildList.addAll(oppId2Obj2Map.get(o.Id)); //add child 2

          String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
          for(Sobject child : genericChildList){

          if(OpportunityHelper.getRecordTypeName(child.get('RecordTypeId')) != rtOpportunity ){
          child.put('RecordTypeId',rtMap.get(rtOpportunity));
          }

          }


          update genericChildList;





          share|improve this answer



















          • 1





            Thanks! I figured it would be something easy.

            – Ixalmida
            Jan 11 at 21:12
















          6














          You can use Sobject get and put method to your advantage. This allows you to dynamically refer and set fiels in any Salesforce Record .



          I would go by adding all children in a Generic List, then iterate over it and assign new recordTypeId accordingly.



          So my code will be like:



          List<Sobject> genericChildList = new List<Sobject>();
          genericChildList.addAll(oppId2Obj1Map.get(o.Id)); //add child 1
          genericChildList.addAll(oppId2Obj2Map.get(o.Id)); //add child 2

          String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
          for(Sobject child : genericChildList){

          if(OpportunityHelper.getRecordTypeName(child.get('RecordTypeId')) != rtOpportunity ){
          child.put('RecordTypeId',rtMap.get(rtOpportunity));
          }

          }


          update genericChildList;





          share|improve this answer



















          • 1





            Thanks! I figured it would be something easy.

            – Ixalmida
            Jan 11 at 21:12














          6












          6








          6







          You can use Sobject get and put method to your advantage. This allows you to dynamically refer and set fiels in any Salesforce Record .



          I would go by adding all children in a Generic List, then iterate over it and assign new recordTypeId accordingly.



          So my code will be like:



          List<Sobject> genericChildList = new List<Sobject>();
          genericChildList.addAll(oppId2Obj1Map.get(o.Id)); //add child 1
          genericChildList.addAll(oppId2Obj2Map.get(o.Id)); //add child 2

          String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
          for(Sobject child : genericChildList){

          if(OpportunityHelper.getRecordTypeName(child.get('RecordTypeId')) != rtOpportunity ){
          child.put('RecordTypeId',rtMap.get(rtOpportunity));
          }

          }


          update genericChildList;





          share|improve this answer













          You can use Sobject get and put method to your advantage. This allows you to dynamically refer and set fiels in any Salesforce Record .



          I would go by adding all children in a Generic List, then iterate over it and assign new recordTypeId accordingly.



          So my code will be like:



          List<Sobject> genericChildList = new List<Sobject>();
          genericChildList.addAll(oppId2Obj1Map.get(o.Id)); //add child 1
          genericChildList.addAll(oppId2Obj2Map.get(o.Id)); //add child 2

          String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
          for(Sobject child : genericChildList){

          if(OpportunityHelper.getRecordTypeName(child.get('RecordTypeId')) != rtOpportunity ){
          child.put('RecordTypeId',rtMap.get(rtOpportunity));
          }

          }


          update genericChildList;






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jan 11 at 21:03









          Pranay JaiswalPranay Jaiswal

          14.9k32653




          14.9k32653








          • 1





            Thanks! I figured it would be something easy.

            – Ixalmida
            Jan 11 at 21:12














          • 1





            Thanks! I figured it would be something easy.

            – Ixalmida
            Jan 11 at 21:12








          1




          1





          Thanks! I figured it would be something easy.

          – Ixalmida
          Jan 11 at 21:12





          Thanks! I figured it would be something easy.

          – Ixalmida
          Jan 11 at 21:12


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Salesforce Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f246391%2fcombining-similar-code-with-different-objects%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Mario Kart Wii

          The Binding of Isaac: Rebirth/Afterbirth

          What does “Dominus providebit” mean?