Salesforce provides one of the most popular and powerful CRM services available on the cloud. Most customers can use Salesforce as is with its default configurations; however there are certain use cases where you need to customize the development to achieve additional workflow or configuration. Take an example such as when you are creating a web or email service. If you want to develop a complex process with additional workflow or a complex validation system for objects, you need to customize your code.
Suppose you are making your own mobile or web-based application, and you want to integrate your application with Salesforce. One of the key requirements to achieving this is to get data from Salesforce on every Salesforce record update. But how do you trigger Salesforce so that it sends you data on every change? Apex is a handy solution to get this done.
Apex is a multitenant language provided by Salesforce to write backend code whenever you want to create your own custom business application. You can write Apex Code in both triggers and classes, and it can be initiated by triggers on the objects or web-service requests.
There are certain rules and best practices for writing Apex Code in Salesforce as a backend developer. It’s good to follow these guidelines in order to make your system both scalable and manageable. One more important aspect that any organization needs to think about is Test Coverage. When releasing Apex Triggers, you can plan proper backup and testing before release of the application.
Our goal is to highlight how to write code that is reusable and suitable for different Salesforce instances. Below you will find several best practices when writing Apex Code that should be implemented to avoid breaking any limitation of the Salesforce platform.
You might also like
How to Clean Your Salesforce Org in 6 Steps
Handling Bulk Data & Other Considerations in Apex Trigger
Many times it happens that we load bulk data of a particular object into the Salesforce system from an external system or source (like through an Excel file). If there is any trigger written on the object for which data is being loaded, the code of that trigger should be so that it is able to handle that bulk data, not just a particular record (unless it’s really needed).
For this, we need to use Trigger.New and Trigger.Old to get a list of records in trigger. To get a map of records, Trigger.NewMap and Trigger.OldMap can be used. And if we are using any DML operation inside trigger, we should use Database.Insert or Database.Update to be able to control transaction rollback.
- Use only one trigger per object principle.
- Minimize the use of SOQL query and DML operations.
- Avoid trigger recursion via a static variable when performing an update on the same object from the trigger.
The reason behind the principle of only one trigger per object is mainly due to the fact that in Salesforce we don’t have any way to guarantee order of execution for triggers on the same object. Having only one trigger gives us the power to control flow of execution, which in turn allows for easy management.
You might also like our blog
Salesforce Experts on Change Set Limitations
Avoid Salesforce Governor Limits
It’s important to write code in such a way that it does not hit any governor limits as well. This means avoiding SOQL queries, DML operations, and asynchronous calls inside loops. If you are dealing with a large dataset, you can use the limit keyword in SOQL. With large data, you then also have to perform a DML operation on a collection (list) instead of a separate DML for each record. Storage for large data entails using collection variables like Set, Map, and List, and you have to make sure to iterate over this collection.
Lastly, in Apex class try to use minimum getter/setter variables to avoid a view state error on the Visualforce page.
Processing a Synchronous and Asynchronous Transaction to Avoid Governor Limits
As Apex is executed in a multitenant environment, Salesforce enforces certain Governor limits to avoid the execution of Apex Code consuming a huge number of resources. This will ensure that Apex Code does not take advantage of multitenancy and does not monopolize shared resources. In Apex you can perform both synchronous and asynchronous transactions. So, you have to write code in such a way that it will not hit any governor limits.
This means you have to use a future method, batch class, or queueable class for situations when you need the transaction to be asynchronous. This is due to the fact that for quite a few cases the total limit includes both synchronous and asynchronous transactions.
Use of Interface, Inheritance Class in Apex
Inheritance is a concept of Object Oriented Programming System (OOPS) that helps to inherit/extend properties of a class into the inheriting class. Inheritance, being one of the fundamental concepts of OOPS, helps in Salesforce to keep the common logic in one class; extended classes then get that logic without any need for individual implementation.
For the abstract layer of Apex Code, you should use interface and/or abstract class.
- An interface is used for defining the basic structure (signature) of a method.
- An abstract class is used to separate out common code (methods and/or properties).
You can consider using either an interface or an abstract class during the design phase. They both allow you to separate out common code in order to make it reusable and manageable.
You might also like our blog
Salesforce Project Management – DIY Changes vs Hiring a Pro
Common Trigger Framework for a Trigger on All Objects
We already mentioned how we need to have only one trigger per object since you can’t handle the order of execution of triggers in Salesforce. In order to create a trigger covering all objects, you need to create a helper/handler class in the trigger and try to write much less code in the trigger itself. Most of the code can be included in this helper/handler class, and then you need to incorporate a common trigger framework. You can refer here for one of the better and more common Apex trigger frameworks as an example.
Also keep in mind that while working on the Apex trigger, it’s good to have that helper/handler class so we can call it from the trigger. Having handler/helper classes will help make trigger code reusable as well more manageable.
Avoid Mentioning Salesforce ID in Class & Use of Constant
One more thing to avoid: hardcoding Salesforce ID in a class or trigger. The reason this isn’t a good thing is because it can impact functionality since code won’t be dynamic any more. Additionally, if we have more variables with a static data value, then we can create a constant class which contains all constant variables.
You might also like our blog
Salesforce Sandbox: Managing Changes in Production
Reusability of Apex Code
A key best practice with Apex Code is to always write scalable and reusable code so that it can be reused in another functionality or module. This entails making code generic, so that it can be reused with minimum modification.
Whenever you are writing Apex Code, there are a few important considerations to take into account:
- Make sure the code is error-free.
- Make sure to use a try-catch block in the code for an exception mechanism.
- Follow the exception mechanism to store exceptions in any custom object to track all errors in the system.
- Store important details, including which class and line has thrown an error, to make necessary debugging easier.
Comments and Naming Convention
Another important best practice surrounding Apex Code is the need to follow a proper naming convention. For example, if we are writing a trigger on a case object, then the trigger name should be CaseTrigger. You also have to write proper comments in your code, so that it will be easier for any other person to understand it.
Regularly Backup Code
As you work and test, the Apex Code should always be maintained in a source code repository like GitHub or Bitbucket to ensure multiple developers can work on it at the same time. In this way, sanity of code is maintained. It will also give you a backup of the data should anything accidentally get lost or be changed.
You might also like
Is your customized Salesforce a plate of Spaghetti code?
Release Management & Test Coverage
Finally, and most importantly, when any new apex or code changes are going to be deployed within Salesforce, they must have proper test coverage to be able to deploy. Test coverage basically means that it will work properly with your current system and your apex change won’t break anything. The best way to achieve this is to understand the impact your code will have as well as regularly test and thoroughly manage your releases.
This will ensure that your code will not only get maximum coverage, but will also not negatively impact your existing org, thus giving you a smooth release. Release Dynamix for Salesforce is the perfect tool for this, as it covers all these bases. RDx gives you a full understanding of the impacts your code will have by pinpointing exactly what your code references. It also manages your project’s code tests and releases, which will give you the power to roll back certain changes, giving you a huge amount of flexibility and security.
The above rules and best practices won’t ensure business correctness in the code, but they will certainly help to make your code more manageable, dynamic, reusable, and readable. Following these principles, you have a better chance of not hitting generic governor limits imposed by Salesforce (such as Too Many SOQL, etc.) and improving your application’s performance. The customized development of an app can be an easy aspect in Salesforce, but only if you follow these best practices alongside using helpful tools such as Release Dynamix and GitHub. These tools give you the ability to create, change, and deploy your code safely.