How to properly check for errors in this code?

This code works fine. What I am looking for is how a professional would check for possible errors in the code to prevent Apex errors from generating. In other words, what things would you check for and what doesn't matter. As always, working examples are much more useful to beginners than theory.

Thanks

trigger trgr_Update_BOG_Members_List on BOG_Membership__c (after insert,after update,after delete)  {      ID currID;      Set<Id> accID = new Set<Id>();      if(Trigger.isInsert || Trigger.isUpdate)      {          LIST<BOG_Membership__c> accountMap = [SELECT ID, Contact__r.AccountId FROM BOG_Membership__c WHERE ID IN :Trigger.newMap.keySet()];           for(BOG_Membership__c bog : Trigger.new)         {               accID.add(bog.frm_AccountID__c);         }     }       // DELETE         if(Trigger.isDelete)      {           for(BOG_Membership__c bog : Trigger.Old)          {              accID.add(bog.frm_AccountID__c);          }          }       // Common Operation     List<AggregateResult> aggregates = [ SELECT Contact__r.AccountId , Contact__r.FirstName , Contact__r.LastName FROM BOG_Membership__c WHERE Contact__r.AccountId = :accID GROUP BY Contact__r.AccountId, Contact__r.FirstName, Contact__r.LastName];      system.debug('debug: aggregates size '+aggregates.size() );     Map<Id, Account> parentRecords = new Map<Id, Account>();       String listNames = '';       for (AggregateResult aggregate : aggregates)      {          Id parentId = (Id)aggregate.get('accountId');          String firstName = (String)aggregate.get('FirstName');          String lastName = (String)aggregate.get('LastName');           listNames += firstName + ' ' + lastName + '<br />';          parentRecords.put(parentId, new Account(          Id = parentId, BOG_Members_List__c = listNames          ));      }      system.debug('debug: parentRecords.values() '+parentRecords.values());     update parentRecords.values();  } 

Replay

Your code does not work correctly. You may think it does, but it doesn't. Let's go over that here.

AggregateResult Aliases

Fields are aliased, by default, as expr0, expr1, etc. Since you're not using aliasing, your function should be returning null values. If it works, coincidentally, it may break in the future. Use aliases.

AggregateResult[] aggregates = [ SELECT Contact__r.AccountId AccountId,
                                        Contact__r.FirstName FirstName,
                                        Contact__r.LastName LastName
                                 FROM BOG_Membership__c
                                 WHERE Contact__r.AccountId = :accID
                                 GROUP BY Contact__r.AccountId,
                                          Contact__r.FirstName,
                                          Contact__r.LastName];

Bulk-Safe

Your code won't get all of the values you expect, because you're overwriting the values. Instead, you need to aggregate first, then join them together:

Map<Id, String[]> bcdList = new Map<Id, String[]>();
// ...

for (AggregateResult aggregate : aggregates) {
    Id accountId = (Id)aggregate.get('AccountId');
    if(!bcdList.containsKey(accountId)) {
        bcdList.put(accountId, new String[0]);
    }
    String firstName = (String)aggregate.get('FirstName');
    String lastName = (String)aggregate.get('LastName');
    bcdList.get(accountId).add(firstName+' '+LastName);
}
// Now build the accounts
Account[] accountsToUpdate = new Account[0];
for(Id accountId: bcdList.keySet()) {
    accountsToUpdate.add(
        new Account(Id=accountId, String.join(bcdList.get(accountId, '<br />')
    )));
}
update accountsToUpdate;

DMLException

You should also consider being able to report errors back to the user if the update fails. I won't write this code here, but you should be aware of row lock errors, validation rules, etc. There's a number of reasons why your code could fail catastrophically, and not even give the user a reasonable explanation of why.



Beyond those those three problems, I'd expect professional code to not have the following:

System.debug

Debug statements take time. They are never "compiled out", even if the system is configured not to log at the level you're logging at. You should be using checkpoints to debug code in production, or use sandboxes.

List<T>

With a few exceptions, List<T> is never as efficient as as simply T[]. I always end up replacing them in code I come across. It's seven characters List<...> versus two characters ...[]. For most developers, [] is more meaningful, because it implies an array. Of course, if a company uses List<...> by default, then continue to do so, or convince the company to change, but keep in mind that we do have limits regarding code size; this is just dead weight in a system where we're metered for every keystroke.

There are a few places where the language simply doesn't understand the ...[] syntax, in which case you need to use List<...>. These are rare, though, and you'll probably not run into those until you start getting pretty advanced in your data structures.

Changes To Account (?)

If a record could theoretically change accounts, you might need to use Trigger.old and Trigger.new in "after update" triggers. If this consideration is not necessary, consider adding comments that state why.

Comments

You should include at least one comment somewhere that explains what this thing does without having to read all the code. If you do anything "tricky," you shoud also explain the trick so that people don't assume it's a logic bug (you don't have any "tricks" in here, but keep this in mind for the future).

Combine Data Types

Every line of execution counts against you. Even though our 'lines of execution" has been replaced with "CPU timeout", keep in mind that every semicolon the code passes over involves periodic checks for heap use, CPU time limits, and so on.

The usual way is to use the comma operator:

    String firstName = (String)aggregate.get('FirstName'),
           lastName = (String)aggregate.get('LastName');

This does the same thing, but will save CPU cycles on long lists.

Also, using the + operator on String values are relatively expensive. Using String.join at the end, as described above, results in much better performance.

Category: apex Time: 2016-07-31 Views: 5
Tags: apex

Related post

iOS development

Android development

Python development

JAVA development

Development language

PHP development

Ruby development

search

Front-end development

Database

development tools

Open Platform

Javascript development

.NET development

cloud computing

server

Copyright (C) avrocks.com, All Rights Reserved.

processed in 0.233 (s). 12 q(s)