10 Common Problems in Apex Code Bases

The process of onboarding to a new Salesforce org is always a challenging task. Legacy systems often have many undocumented processes created by Salesforce Admins and Developers, which can make the initial assessment of an org difficult for new users responsible for the ongoing maintenance of the org.

There is more than one way to undertake a technical analysis of an org, but one of the first things I check whenever I am in a new org is the automation and Apex code. In my experience, this is a good indicator of the level of technical debt in the system.

Despite the variability between Salesforce orgs, different orgs often have similar problems. This blog post presents a list of the most common Apex problems I see in client orgs and the recommendations to tackle these challenges.

Common Problems in Apex Code

1. Poor code formatting, improper indentation, extraneous blank lines, etc.

  • If code is not properly formatted, it makes code analysis much more difficult. However, this is probably the easiest problem to address. If you use a code editor such as VsCode for example, you have dedicated tools/extensions (e.g. Prettier) that can reformat your document. This video does a great job of outlining some of Prettier’s features.
  • The Developer Console should not be your go-to tool for writing code on a daily basis. With Code Builder currently in Beta, it looks like VsCode will remain one of the most reliable options to write code as a Salesforce developer.

2. Logic in triggers

  • A separate trigger handler is preferred to host logic, thus decoupling the trigger from the business logic that needs to be executed. One common example can be found in this blog post by Coding With The Force.
  • Maintenance, code reusability, and “with sharing” enforcement are some of the benefits that come with using a trigger handler.

3. Apex Triggers in cases where Record Triggered Flows should be used

  • In most cases, legacy code once helped automate the processes declarative tools could not. Analyze code complexity and if your trigger is only populating field values based on simple criteria, then consider replacing that part of the functionality with either Before or After Flows.
  • This Salesforce Architects page contains useful information that will help you take your Flow skills to the next level.

4. Multiple triggers per object

  • The order in which triggers are executed is not guaranteed in this case, and can make maintenance difficult.
  • The recommended best practice is to merge these together into a single trigger per object and delegate the business logic to a trigger handler.
  • The handler can then orchestrate the order in which the operations need to be performed.

5. Code is not bulkified – In the words of Dan Appleman, “All of your Apex code should be designed to handle bulk operations. All of it – no exceptions”.

  • Apex code should be designed to operate SOQL and DML on collections of sObjects.
  • This also includes invocable apex methods which are infrequently bulkified. Even if the invocable method is used in a screen flow, there is nothing stopping another developer from reusing the same code somewhere else in the application where bulk patterns do matter.

6. Test classes do not contain assert methods to validate that the code is working correctly

  • This might not be considered problematic at first. The importance of test classes is often overlooked but it becomes self-evident as soon as one starts refactoring code or works on new functionality. Having a good test suite ensures that you do not accidentally break existing functionality.

7. Large portions of code are commented out

  • When this is the case, it is better to simply clean up the code if it no longer serves a purpose. Version control software and code hosting platforms such as GitHub or BitBucket can be used to refer back to previous versions of the code. To expand on this topic, Clean Code by Robert C. Martin has an informative chapter on code comments.

8. Apex methods span hundreds of lines

  • This usually is accompanied by a second issue where there are multiple levels of code nesting.
  • It goes without saying that code that suffers from this problem reduces readability and makes troubleshooting extremely difficult.
  • A first step in addressing this issue is to write code with the Single-responsibility principle in mind.

9. Asynchronous processes are not actively monitored

  • Inspect the Scheduled Jobs page in Salesforce Setup to see which jobs are scheduled to run on a daily basis. It is important to verify if the list contains any processes that are no longer needed. As business requirements change, it is to be expected that some batch jobs become obsolete over time.
  • Monitor the Apex Jobs page and take note of how long it takes on average for bulk jobs to execute. It is really important to check if your expectations match reality. For example, if you have a batch job responsible for updating account records on a daily basis and that usually takes approximately 30 minutes to execute, then you would expect that to be the case on the following day. If instead it took one hour, then there’s a good chance that something meaningful produces that change. Perhaps there was a data load on the previous day and now the batch class needs to process more data, or the Apex Class was updated, either way, it is important to know the context.
  • Check the Apex Jobs page for any apex errors.

10. Apex Exception Email only sent to default “LastModifiedBy”

  • By default, whenever an unhandled exception occurs, Salesforce will send an email to the developer specified in the LastModifiedBy field. In some cases, that developer is not necessarily the person who should be taking action to remedy the situation (especially in larger organizations where there are dedicated members to monitor/support). In addition to the default, a list of other recipients can be configured in Salesforce Setup on the Apex Exception Email page.

While this is not an exhaustive list of everything that should be examined in a technical analysis, these are some of the main culprits when it comes to common problems. By tackling and correcting these issues, you’ll be well on your way to optimizing your org and limiting the technical debt.

You may be interested in

How to Use Lightning Web Component Slots

How to Use Lightning Web Component (LWC) Slots

Lightning Web Component Slots are a valuable tool for any Salesforce Developer to add to their arsenal. In this blog, we’ll review what they are, what they do, and how to use them. What are LWC slots? A slot ( ) is a placeholder for markup that a parent component passes into a component’s body. […]

Read More

What is Omnistudio?

What is Omnistudio?

What is OmniStudio? (And how can I use it?) OmniStudio is a low-code development platform that allows businesses to build custom applications quickly and easily. It helps to simplify the creation of complex, industry-specific experiences on Salesforce. It is an all-in-one platform that offers a range of tools and features to help businesses develop and […]

Read More

Sign up for the latest tips & news from CloudKettle

Thank you for subscribing.