Table of Content
What You’ll Learn
- Best practices for writing and managing Apex classes and triggers in Salesforce.
- Techniques for handling bulk data and avoiding Salesforce governor limits.
- The importance of using interfaces, inheritance, and common trigger frameworks.
- Guidelines for exception handling, comments, naming conventions, and code backups.
- The role of release management and test coverage in successful deployments.
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 Trigger 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 Salesforce 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
Salesforce Apex Code Changes – The Expert guide
———-
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.
Further considerations:
- 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.
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.
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.
Exception Handling
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 our blog
Salesforce Experts on Change Set Limitations
———-
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. Panaya ForeSight for Salesforce is the perfect tool for this, as it covers all these bases. Panaya ForeSight 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.
Conclusion
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 Panaya ForeSight and GitHub. These tools give you the ability to create, change, and deploy your code safely.
Key Takeaways
- Ensure triggers handle bulk data using Trigger.New, Trigger.Old, and use Database operations to control transaction rollbacks.
- Write code to avoid governor limits by minimizing SOQL queries, DML operations, and asynchronous calls inside loops.
- Implement interfaces and abstract classes for common logic to promote code reuse and maintainability.
- Use a single trigger per object with helper/handler classes to manage code flow and execution order.
- Use try-catch blocks for error handling, store exceptions for debugging, and ensure error-free code.
- Follow proper naming conventions and add comments for clarity and ease of understanding.
- Maintain code in repositories like GitHub or Bitbucket, ensure proper test coverage, and use tools like Panaya ForeSight for impact analysis and release management.
Frequently Asked Questions
Apex triggers in Salesforce are code snippets that are executed when specific events occur on Salesforce objects, such as when a record is created, updated, or deleted. Triggers allow developers to customize the behavior of Salesforce by adding business logic, validating user input, or interacting with external systems. Triggers are written in Apex, a proprietary programming language used by Salesforce.
There are two types of Apex triggers in Salesforce: Before Triggers and After Triggers. Before Triggers execute before the record is saved to the database, while After Triggers execute after the record has been saved. Within each type, there are three sub-types: Insert Triggers, Update Triggers, and Delete Triggers.
There are two types of Apex triggers in Salesforce: Before Triggers and After Triggers. Before Triggers execute before the record is saved to the database, while After Triggers execute after the record has been saved.
Want To Learn More About Panaya ForeSight?
- Start your free trial of ForeSight for Salesforce
- Check out our Resource Center
- Follow us on Linkedin, Twitter, YouTube and Facebook
We’re Hiring!
Apply now on our Career Center