html code

Five Common Errors to Steer Clear of When Studying Apex Code

Being a dedicated Salesforce Architect and Developer, I’ve authored a considerable amount of code and provided guidance to numerous professionals throughout my career. Sharing knowledge brings me immense satisfaction, and today, I want to impart some valuable insights by highlighting common errors that should be sidestepped when delving into coding, particularly in the context of Salesforce’s Apex programming language.

1. Neglecting to Grasp the Full Potential of the Programming Language

When embarking on your coding journey, it’s essential to thoroughly acquaint yourself with its capabilities and constraints. Utilize available resources and engage in ample practice. It took me several months to grasp the fundamentals, encompassing concepts like variables, operators, conditional statements, loops, collections, and functions. Object-Oriented programming, on the other hand, required even more time to master effectively.

To illustrate, a recent client approached me with concerns about encountering the notorious Apex CPU Timeout Limit Error in their Apex code. Upon examining the code, the primary issue emerged: it needlessly compared child records with their parent records after separately querying them in two distinct SOQL queries. The original developer should have employed a single SOQL query with a sub-select to retrieve all the necessary information.

Here’s an example of the problematic code snippet:

List<Account> accounts =
[SELECT Id,
                Name
    FROM Account
   // Criteria Here];
 
List<Contacts> contacts =
[SELECT Id,
                Name,
                AccountId
    FROM Contact]
 
for (Account acct : accounts) {
    for (Contact con : contacts) {
 
        if (con.AccountId == acct.Id) {
             // Do stuff
        }
    }
}

This code resided within Batchable Apex, which already enjoyed the extended 60-second Apex CPU limit.

However, the code exhibited significant inefficiency. For each account, it traversed through all the contacts to identify those specific to that particular account before performing any actions.

Consider a scenario with, let’s say, 500 accounts and 1,000 contacts; this would result in 500,000 iterations – a considerable amount of unnecessary processing.

The original developer appeared to be unaware of Sub-Selects in SOQL queries, a feature that allows you to retrieve child records associated with each parent record automatically.

A more efficient version of the code is provided below:

	
List<Account> accounts =
[SELECT Id,
                Name,
                (SELECT Id,
                                Name
                     FROM Contacts)
    FROM Account
    // Where Clause Here for Desired Accounts];
 
for (Account acct : accounts) {
    for (Contact acctContact : acct.Contacts) {
       // Do something with each account’s contact as needed
    }
}

Now, this code demonstrates significantly improved efficiency as it only iterates through the contacts associated with each returned account

2. Replicating Code Through Copy-Paste

One of the phrases I often share with my mentees is: “If you find yourself repeatedly copying and pasting code, it’s a sign that you might want to reconsider your coding approach!” While it might sound a tad dramatic, it effectively conveys the importance of this practice (and, naturally, I keep it suitable for all audiences).

Copying and pasting code can lead to challenges in the long run, primarily concerning maintenance. When code is copied multiple times and then a modification becomes necessary, that change must be applied universally; otherwise, it can lead to the emergence of bugs.

A more efficient approach involves utilizing functions. A function can be employed throughout a class or the entire codebase, accessible to anyone based on its visibility settings. A well-crafted function should have a single, well-defined purpose and execute it proficiently. When a modification is required, you only need to make that change in one place within the codebase.


3. Creating Lengthy Functions

The typical individual can retain between 7 to 12 items in their working memory simultaneously. However, when dealing with lengthy functions, such as those exceeding 50 lines of code, one often needs to juggle more than the 7-12 item limit in working memory. This complexity not only makes the code harder to grasp but also increases the likelihood of introducing errors.

A remedy to this issue involves crafting shorter functions that leverage helper functions. Instead of having a single long function, the main function makes use of multiple shorter ones. In my practice, I advocate keeping functions within 50 lines of Apex code or fewer. Others might propose even shorter limits, such as 20 or 30 lines. The general principle is that “shorter is better,” allowing you and your team to determine the most suitable length based on your specific needs.

4. Excessive Nesting of Code

Code characterized by excessive nesting is also more challenging to understand and is susceptible to a higher likelihood of bugs.

public List<Account> getAccountsWithCountry(List<Account> accounts) {
    List<Accounts> accountsWithCountry = new List<Account>();
 
    if (accounts != null) {
        for (Account acct : accounts) {                          // First Level Of Nesting
            if (String.isNotBlank(acct.BillingCountry)) {  // Second Level of Nesting
                accountsWithCountry.add(acct);              //  Third-Level of Nesting
            }
        }
    }
 
    return accountsWithCountry;
}

This code sample is a public function with three tiers of nesting:

  1. A “for-each” loop that iterates through the accounts.
  2. An “if” statement.
  3. The section of code responsible for adding the “acct” to the “accountsWithCountry” collection.

This code is acceptable, but it’s not optimal. If there are numerous additional tasks that need to be performed inside the for loop or within the if statements, the readability and comprehension of this code can deteriorate significantly.

It’s advisable to aim for code with no more than two levels of nesting. One approach to achieve this is by reversing the logic. Instead of continuing only if the accounts are null, first check if they are null and halt if they are. For instance:

public List<Account> getAccountsWithCountry(List<Account> accounts) {
    List<Accounts> accountsWithCountry = new List<Account>();
 
    if (accounts == null) {
        return accountsWithCountry;
    }
 
    for (Account acct : accounts) {
        if (String.isNotBlank(acct.BillingCountry)) {
            accountsWithCountry.add(acct);
        }
    }
 
    return accountsWithCountry;
}

This code accomplishes the same task while maintaining only two levels of nesting. Additionally, it offers the advantage that if you reach the “for-each” loop, you can be assured that the “accounts” list is not null, making it safe to iterate through.

5. Poor Code Formatting

It’s essential to aim for properly formatted code as it greatly enhances readability and comprehension. Poorly formatted code typically lacks proper white space and indentation. While the Apex compiler is capable of interpreting code thanks to semicolons, parentheses, braces, and other syntax, it disregards white space. However, developers rely on white space to facilitate the ease of reading and understanding code!

Example of Poorly Formatted Apex Code:

public class MyBadFormatClass {
public String FirstName=''; public Integer Age=0; public String LastName='';
public String getName() { return FirstName + ' ' + LastName; }
}

This class is compilable but proves quite challenging to read and understand. The second line declares three variables, while the third line contains a function. Let’s proceed to reformat it for clarity…

Example of Well-Formatted Apex Code:

public class MyBadFormatClass {
    public String FirstName = '';
    public Integer Age = 0;
    public String LastName = '';
 
    public String getName() {
        return FirstName + ' ' + LastName;
    }
}

Closing Remarks

I trust that this has aided you in recognizing, comprehending, and steering clear of the typical blunders made by Salesforce professionals as they embark on their coding journey.

Enjoyed the content here? Be sure to explore my “Introduction To Salesforce Apex Course,” where you can delve much deeper into the subject matter.