Salesforce Apex Triggers: Best Practices to Avoid Design Issues
Apex triggers are code scripts that run automatically when a Salesforce record is inserted, updated, or deleted. These triggers can be used to build automated processes or prevent certain actions from happening during data manipulation. For example, one could develop an Apex trigger on opportunities to notify the primary contact when the opportunity is closed. Another example could be using a trigger on accounts to prevent users from adding a new account if a phone number is already specified.
Apex triggers are useful for creating complex automations that cannot be accomplished using other declarative tools like Flow, Process Builder, or Workflow Rules. However, as the number of triggers on an object increases, it can lead to difficulties in maintaining and debugging the code, decreased performance efficiency, and hitting governor limits, among other issues. To mitigate these challenges, it's advisable to follow one of the trigger frameworks provided by the Salesforce Developer Community.
When to Use Apex Triggers Over Flows
Complex automations that cannot be executed declaratively through tools such as Flow, Process Builder, or Workflow Rules can be accomplished through the use of Apex. Apex is suitable for scenarios such as when a flow requires nested loops, the "Get element" function within a loop, handling large data volumes, implementing custom integrations, and logging errors in the event of automation failure.
Apex triggers and flows serve different purposes and are used in different situations. Apex triggers are best used for automating complex business logic that can't be handled by point-and-click solutions like flows or process builders. Flows, on the other hand, are best used for guiding users through a process, collecting information from users, updating records, and providing a visual representation of a process.
Here are some general guidelines to help you decide between using an Apex trigger or a flow:
Use Apex triggers when you need to:
- Automate complex business logic that can't be handled by point-and-click solutions
- Interact with multiple objects in a single transaction
- Create, update, or delete records based on specific conditions
- Perform custom validation on records before they are saved
Use flows when you need to:
- Guide users through a process
- Collect information from users
- Update records
- Provide a visual representation of a process
- Automate simple business processes that can be handled by point-and-click solutions
In summary, use Apex triggers when you need to automate complex business logic, and use flows when you need to guide users through a process and automate simple business processes.
Lightweight Trigger Framework
The main idea of the trigger framework is to have a trigger handler class for the apex trigger. Instead of writing automations in triggers, we can separate those automations into different functions in the trigger handler class. These trigger handler functions will be called from the trigger. You can find the example code snippet below:
- Writing automations using the trigger framework will help in debugging and maintaining the code.
- We can easily fix a bug or add a new feature in this type of code base. If we want to add new automation on the Account object, we can develop a separate function in the AccountTriggerHandler class and call it from the relevant trigger event in the Account trigger.
- Trigger framework will control the order of execution of trigger on the object. As there will be one trigger handler, so you can control which business process to run first and so on.
Advanced Trigger Framework
Earlier, we discussed the basic architecture of a trigger framework. To take it a step further, consider adopting an advanced trigger framework where a parent trigger handler class contains general functions that run on record insert, update, and delete. The trigger handler classes for other objects then extend from this general trigger handler class. This framework offers improved control over method execution and prevents recursive trigger calls. A sample of such a trigger handler framework is shown below:
We can see how the general code moves from the Account trigger to the parent trigger handler class’s ‘run’ function. The main benefits of an advanced trigger framework in addition to a lightweight trigger framework are as follows:
- Prevent recursive trigger calls and improve performance.
- Reusable and consistent structure for all object triggers which will increase the productivity of old as well as new developers.
- This framework provides us with a way to bypass the trigger logic from some endpoints.
- Keep the general validations in the parent trigger handler which can be imposed on all objects.
We have shared with you some of the most commonly used trigger frameworks. You can find additional trigger frameworks on GitHub. The choice of which framework to use depends on the size and specific needs of your organisation. We recommend starting with a lightweight trigger framework and gradually building upon it as your organization grows in size and complexity.
If you require any assistance in implementing a trigger framework for your Salesforce organisation, please don't hesitate to reach out to us. We are here to help.