Top 12 Best Practices for Apex Code to Become A Better Developer

Summary:This blog describes the top 12 best practices of Apex programming for Salesforce developers. It will help them become better coders and improve their skills to match those of experts in the industry.

Salesforce provides a powerful core set of services to all customers in the multi-tenant cloud. No matter your size, you get access to the same tools. To share these resources between you and other customers, Salesforce has created policies to make sure that everyone can make the most of That’s why they’ve set a few limits.

As a beginner, you must keep in mind that apex code is the foundation of any customizations you might make. It is a complex and robust object-oriented extension of the Salesforce platform. To strengthen your coding skills, you must follow some best practices. To become a top-notch Salesforce developer, read through these tips and tricks and then practice them until you become perfect at them!

Table of Contents

  • Apex Code Tips Every Developer Must Know
  • Advisory For Controller/Extension Class Usage
  • Some Best Practices For Triggers
  • Governor Limits of @Future Method
  • Some Best Practices For Apex Test
  • Wrapping It Up

Apex Code Tips Every Developer Must Know

Here is a list of the top 12 best practices that you should follow to run the Salesforce apex code smoothly:

  1. Structured queries and data manipulation language (DML) statements are better executed outside of FOR loops.
  2. Be sure to bulkify your code to ensure that it will handle data properly involving multiple records.
  3. When you’re running Apex, it’s easy to miss a governor limit, but with the Limits Apex Method, you can avoid reaching them in your code.
  4. Before executing, check whether the code exceeds any governor limits. Here is an example showing how to check for governor limits:

if (opptys.size() + Limits.getDMLRows() > Limits.getLimitDMLRows()) {

//logic here


5. There are several ways around the heap limit exception. One way is to use a SOQL query for loop. Here is an example for it:

Account[] accts = new Account[];

for (List<Account> acct : [SELECT id, name FROM account WHERE name LIKE ‘XXXX’]) {

// Your logic here



6. Always avoid hard coding IDs — they don’t work because even if you deploy Apex to two Salesforce environments, for example, Dev/Prod, there is no guarantee that IDs will be the same in either. By doing so, if the record IDs change between environments, the logic can dynamically identify the proper data to operate against and not fail.

7. It is a good practice when creating a class is to use the “with sharing” keyword. This keeps the instances of the class accessible from outside of the class.

8. You should use filters in SOQL queries to limit the number of records returned by the query. If you don’t, the query will return too many results which may cause it to exceed the limit.

9. Use collections to Insert or Update records, but one DML statement can only update 10,000 records in a single transaction.

10. It is a best practice when writing triggers on case objects, the trigger name should be CaseTrigger. It is also essential to comment on your code properly so that it is easier for any other coder to understand your logic.

11. Don’t forget to use Try catch blocks for exception handling. With Apex, you can write code that responds to specific exceptions. For example:

catch(System.DmlException DML) -> Usually shows because of a required field not being set, where a record has been deleted.

catch(System.QueryException que) -> Usually, this means the query is returning over one result.

catch(System.NullPointerException null) -> Usually caused by not initializing a variable and then trying to do some sort of operation on it.

12. If you are performing a CRUD operation, make sure you check the field and object permission for the user who is running the class. For example,

if (Schema.sObjectType.Contact.fields.Email.isUpdateable()) {

//check for others too -> isCreateable,isAccessible,isDeletable

// Update contact phone number


Advisory For Controller/Extension Class Usage

If you use an Apex controller or an Apex extension class, make sure not to execute database operations when someone loads the page. It would be better to perform any operation only when the user clicks a button.

Some Best Practices For Triggers

Here are some tips and tricks to using triggers in your APEX code:

#1 Use Them Economically: Do not create multiple triggers on a single object because you do not have control over which trigger gets initiated first. Second, each trigger that is invoked does not get its governor limits. Instead, all code that is under processing including any additional triggers, share the available resources.

#2 Use Apex Classes: Avoid using complex logic within your triggers. Delegate the execution logic to classes containing Apex code. To make it easy to run tests and reuse code, put your execution logic inside of Apex classes, and have triggers execute that class.

#3 Make Use of Helper Class: If your class or method is giving several other classes or methods its functionality and/or state, make it a “helper” instead. Rather than creating helpers for specific reasons, rework your code to use the same “helper” class or method across all contexts.

#4 Maximum Efficiency: If you use triggers to process large batches of data, they should be able to handle batches of up to 200 records.

#5 Use Collections Instead: In database systems, it’s usually best to do things in batches instead of one at a time. By operating on entire collections of data instead of single records, an application can work faster because of the amount of data being processed. Hence, it is better to execute DML statements using collections instead of individual records.

#6 Use Appropriate Names: By using a consistent naming convention for all of your triggers, you will make it easy to identify which trigger does what. You can put the object name at the beginning of the trigger and any other descriptive information at the end. For example, AccountTrigger.

Governor Limits of @Future Method

Here is a list of governor limits that apply to the @future annotation:

  • The maximum number of calls allowed per Apex transaction is 10.
  • The maximum number of calls per Salesforce license within 24 hours is 200.
  • This method requires that all the parameters are simple values or arrays of simple values or collections of simple values.
  • Methods with future annotation do not take sObjects or other objects as arguments.
  • Methods that are annotated as @future cannot be used in Visualforce controllers, in either getMethodName, setMethodName or the constructor.

Some Best Practices For Apex Test

Following are some suggestions that can be useful while coding or testing in Salesforce:

#1 Use of Test.startTest and Test.stopTest: When executing tests, code called before Test.startTest and after Test.stopTest receive a separate set of governor limits than the code called between Test.startTest and Test.stopTest. This allows for any data that needs to be set up to do so without affecting the governor limits available to the actual code being tested.

#2 The System.assertEquals Method: It is essential to use the System.assertEquals(expected, actual) with every test method.

#3 Efficient Use of seeAllData Parameter: Only put (seeAllData = true) in test class if you have a good reason for it.

#4 Use Of System.runAs Method: Use the System.runAs() method whenever you need to test whether a certain function works well in user contexts.

Wrapping It Up

This is where we end our discussion. Hope that with the above Apex best practices you can improve your programming skills and make your code more readable, manageable, and reusable. This post covers all the essentials that you need to become a better developer. It will guide a beginner to become an intermediate coder in no time. Refer to this blog whenever you feel like your code may hit governor limits. Till then keep coding and keep growing!

Aakansha Bhatnagar

Leave a Reply

Your email address will not be published. Required fields are marked *