As an avid Salesforce Architect and Developer, I’ve written lots of code and helped to mentor various professionals during my career.
Sharing knowledge is one of my greatest joys, so today I’d like to share some common mistakes that are best avoided when learning to code – specifically in relation to Salesforce’s Apex programming language.
1. Not Learning the Programming Language’s Capabilities
When learning to code, ensure you know all its capabilities and limitations by using the resources available and practicing a lot. It took me a few months to learn the basics, including variables, operators, if statements, loops, collections, and functions. It took me longer to learn Object-Oriented programming effectively.
For example, a client recently asked me why their Apex code was encountering the dreaded Apex CPU Timeout Limit Error. After inspecting the code, the biggest culprit was that it was unnecessarily matching child records with their parent records after querying them separately in two different SOQL queries. The original developer should have used a single SOQL query with a sub-select to get all the information.
Here’s an example of what it looked like:
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 was in Batchable Apex, so it already had the higher 60-second Apex CPU limit.
However, this code is very inefficient. For each account, it goes through all the contacts to find those specific to this account to then do something with.
If there are, let’s say, 500 accounts and 1,000 contacts, that is 500,000 iterations – which is a lot of unnecessary processing.
The original developer did not know about Sub-Selects in SOQL queries, which allow you to fetch child records related to each parent record (it does this automatically for you!).
The more efficient code is as follows:
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 is much more efficient and only runs through the contacts on each account returned.
2. Copy and Paste Code
One of my favorite things to tell mentees is this: “If you’re copying and pasting code, please chop your hands off!”. That sounds a bit graphic but it gets the point across (even though I tend to keep it ‘rated G’).
Copy and pasting code is bad due to long-term maintenance. If the same code is copied repeatedly and then a change is required, that change has to be applied everywhere – if it’s not applied everywhere, bugs occur.
One solution is to use functions. A function can be used throughout a class or codebase by anyone, depending on its access level. A function should do only one thing and it should do it well. If a change is needed, only one place in the code needs to change.
3. Writing Long Functions
The average person can keep 7-12 items in their working memory at any given time. However, when a function is long, say more than 50 lines of code, one often has to keep track of more than 7-12 items in working memory at once. This makes the code harder to understand and more prone to bugs.
One solution is to write shorter functions that use helper functions. Instead of one long function, the main function uses multiple shorter ones instead. My guideline is to keep functions to 50 lines of Apex code or less. Others may say 20 lines or 30 lines. The general guideline is ‘the shorter the better’ – you and your team can choose the appropriate length for you.
4. Code Nested Too Deep
Code that is nested too deep is also harder to reason about and more prone to 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 example is a public function that has three levels of nesting:
- The “for-each” loop iterating over the accounts.
- The “if” statement.
- The code adding the acct to the “accountsWithCountry”.
This code is OK, but not great. If there are many other things that have to happen inside the for loop or within the if statements, this code becomes much harder to read and understand.
Strive to keep your code to no more than two levels of nesting. One way to do this is to invert the logic. Instead of only proceeding if the accounts are null, check if it’s null first and stop if it is. For example:
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 does the same thing but only has two levels of nesting. It also has this added benefit: if one gets to the for-each loop, the accounts list is not null and one can safely iterate through it.
5. Bad Formatting
One should strive for well-formatted code – this makes it easier to read and comprehend. Badly formatted code often has no white space and no indentation. The Apex compiler knows how to read code which is why one has semicolons, parentheses, braces, and other syntax. The Apex compiler ignores white space. However, developers need it to easily read and understand code!
Apex Bad Formatting Example:
public class MyBadFormatClass {
public String FirstName=''; public Integer Age=0; public String LastName='';
public String getName() { return FirstName + ' ' + LastName; }
}
This class compiles but is really hard to read and comprehend. The second line declares three variables and the third line is a function. Let’s reformat…
Apex Good Formatting Example:
public class MyBadFormatClass {
public String FirstName = '';
public Integer Age = 0;
public String LastName = '';
public String getName() {
return FirstName + ' ' + LastName;
}
}
Final Thoughts
Hopefully this has helped you to identify, understand, and avoid the most common mistakes Salesforce professionals make when learning to code.
Like what you read here? Check out my Introduction To Salesforce Apex Course that goes into a lot more detail.