Apex Triggers are very powerful and are easily one of the most important parts of Salesforce because they significantly impact all database operations (inserts, updates, deletes, etc. ) With this incredible power and flexibility thereās a lot of room for problems. In my career as a Salesforce developer, Iāve looked at hundreds of different apex triggers and realized there are a lot of points of failure with apex triggers. This post is a very high level list of best practices and why they are important for apex triggers.
I donāt believe that anybody goes out of their way to intentionally create bad triggers. Triggers usually start out very small and expand over time as they expand, we need to understand and constantly improve them. I hope to expand on this post a lot more over time and provide examples of how to refactor a trigger because itās hard to improve if you donāt understand thereās a problem and what the alternatives are.
Before reading this post, I recommend that you understand how triggers function. For example, you need to understand howĀ before and after triggers workĀ and have a decent understanding of theĀ Salesforce Order of Execution.
Use a Trigger Framework
Trigger Frameworks help significantly reduce the amount of development effort involved in creating and maintaining triggers. Trigger Frameworks offer a ton of other benefits like Enforcing Consistency of Trigger Logic, simplify testing, and helping conform to Apex Trigger Best Practices.
Trigger Frameworks offer a centralized and standardized way of providing a trigger kill switch and detecting recursive triggers. Some of the better trigger frameworks even can detect if they are being called recusively and allowing some to be called recursively. Kevin Poorman in his bookĀ Master Application Development with Force.comĀ covers Trigger Frameworks quite extensively. Iāve also put together a post aboutĀ Choosing Apex Trigger FrameworksĀ and some of the things you need to consider.
Objects Should Have As Few Triggers as Possible
Ideally, a Salesforce object should only have one trigger because it makes it easier to predict the order in which operations will be conducted. In his book, Advanced Apex Programming, Dan Appleman coined the phrase āOne Trigger to Rule Them Allā to explain this concept.
In general, I think itās truly a best practice even though it is a bit controversial and can be difficult for somebody nontechnical to figure out whatās going on. In some situations, it may make sense to split up triggers based on the different trigger contexts. For example, a delete trigger probably doesnāt need to do any of the same operations that an insert or update trigger would need to do.
Triggers should contain no logic
Triggers should contain absolutely no logic and should instead called an apex class that can handle the Trigger.new list or the Trigger.OldMap. By separating this logic into another class and calling it we can follow the separation of concerns principle which means the code and trigger will be more maintainable and possibly easier to debug.
By moving trigger logic into a separate class, we are able to unit test a lot easier because we donāt necessarily need to initiate DML operations and we can handle lots of scenarios which may not technically be valid right now. Small separate functions also allows us to fully unit test and do integration tests on the trigger.
Code Called by Triggers Must Have Great Code Coverage
The code that the trigger uses must have a lot of code coverage that contains asserts and tests each of the logic paths. An exception being thrown in a trigger can cause records not to be inserted or updated, debugging the code can provide incredible difficult, and as most developers knowĀ deploying apex to Salesforce can take a very long time.
Use Collections like Sets, Maps, and Lists
All triggers execute in a batch context which meands that when a trigger fires it could update multiple records at the same time. Itās incredibly important to use Apex Collections to query data and store data. By using the proper collection itās also possible to create extremely efficient queries and for loops.
Maps are extremely efficient for storing data and find elements without having to use for loops. Sets can easily be used to check for duplicates ad to reduce the number of duplicates. Iāve written about how toĀ convert lists to sets and mapsĀ and strongly recommend understanding the concepts.
Bulkify All Code
Itās incredibly important that all code called by an apex trigger can handle 200 records. For small Salesforce orgs, this doesnāt seem like a problem but it can be a problem if you or your admins are using the data loader frequently.
Code that looks like this needs to be changed, because it will use too many soql queries and wonāt perform all that well
1
2
3
4
5
|
for (Account acc : Trigger. new ) { Ā Ā Ā Ā User usr = (User)[select Id, FirstName, LastName from User Where Id =: acc.OwnerId]; Ā Ā Ā Ā Ā Ā Ā Ā doSomething(acc, usr); } |
The change needs to be something more like this:
1
2
3
4
5
6
7
8
9
10
11
12
|
Set<Id> ownerIds = new Set<Id>(); for (Account acc: Trigger. new ) { Ā Ā Ā Ā ownerIds.add(acc.OwnerId); } Map<Id, User> users = new Map<Id, User>([select Id, FirstName, LastName from User Where Id IN: ownerIds]); for (Account acc : Trigger. new ) { Ā Ā Ā Ā User usr = users.get(acc.OwnerId); Ā Ā Ā Ā Ā Ā Ā Ā doSomething(acc, usr); } |
Avoid hardcoding Ids
Hardcoding Ids inside of trigger logic or code anywhere else is a bad idea because itās difficult to maintain and often the Ids are different between environments. If you require an Id for something you should store the values in aĀ Custom SettingĀ orĀ Custom Metadata Type.
Check back in the future, I plan to provide additional blog articles about Apex Triggers as I feel they are an essential part of the Salesforce architecture.
To ensure a good time between the sheets, there are some things that you simply cannot ignore. As girls are the most sought after in Vadodara, we know what we talk about when we talk about good sex. If your appointments were left dissatisfied with you, we may be able to help you. Before your next appointment, do not forget the following essential principles.
They are in great demand these days and during topical events demand independent femaleĀ Mussoorie escort serviceĀ that provide escort services to girls become truly unreliable. The various services and exciting perks offered by them always prove to be one of the foremost factors determining the overall success of Escort agencies based in Mussoorie. These Mussoorie girls provide impeccable call and out call service
here are so numerous Mussoorie escort service number to choose from but, be warn, not all call girls agencies are the identical. We are a budget Escort service call girls and as such we want to remain the original price as low as probable book on whatsapp number. We be likely to draw girls new to Mussoorie and new to the business. That income whatsapp number escorts in Mussoorie. we forever have fresh girls pending onto our book, some implausible girls in reality. We work solid to remain them full of activity, to remain them, and you, pleasedĀ Mussoorie call girlsĀ but we recognize that the attract of superior change will forever entice them left to the more expensive service in India. Thatās foreseeable so we for perpetuity tell our customers, if you observe a young woman you akin to volume her as quickly as you can meet the expense of it.It was Sonakshiās sexy Mussoorie escort service that he needed at that point of time. So without wasting any time further, he decided to give her a call and enquirer whether she is available at that moment. Sonakshi at one point of time had been one of the most successful Mussoorie independent escorts and her services and well established goodwill have always helped her with extreme popularity, fame and demand. Raghav on an earlier date remembers visiting one of the top reputed lists of independent escorts in Mussoorie where he noticed the name of Sonakshi being listed at the top. This made him feel even more confident that he is about to have a real good moment with this busty babe.
What is a Class?
A class is a template or blueprint from which objects are created. An object is an instance of a class. This is the standard definition of Class. Apex Classes are similar to Java Classes.
For example,Ā InvoiceProcessorĀ class describes the class which has all the methods and actions that can be performed on the Invoice. If you create an instance of this class, then it will represent the single invoice which is currently in context.
Creating Classes
You can create class in Apex from the Developer Console, Force.com Eclipse IDE and from Apex Class detail page as well.
From Developer Console
Follow these steps to create an Apex class from the Developer Console ā
Step 1Ā ā Go to Name and click on the Developer Console.
Step 2Ā ā Click on File ā New and then click on the Apex class.
From Force.com IDE
Follow these steps to create a class from Force.com IDE ā
Step 1Ā ā Open Force.com Eclipse IDE
Step 2Ā ā Create a New Project by clicking on File ā New ā Apex Class.
Step 3Ā ā Provide the Name for the Class and click on OK.
Once this is done, the new class will be created.
From Apex Class Detail Page
Follow these steps to create a class from Apex Class Detail Page ā
Step 1Ā ā Click on Name ā Setup.
Step 2Ā ā Search for ‘Apex Class’ and click on the link. It will open the Apex Class details page.
Step 3Ā ā Click on ‘New’ and then provide the Name for class and then click Save.
Apex Class Structure
Below is the sample structure for Apex class definition.
Syntax
private | public | global [virtual | abstract | with sharing | without sharing] class ClassName [implements InterfaceNameList] [extends ClassName] { // Classs Body }
This definition uses a combination of access modifiers, sharing modes, class name and class body. We will look at all these options further.
Example
Following is a sample structure for Apex class definition ā
public class MySampleApexClass { //Class definition and body public static Integer myValue = 0; //Class Member variable public static String myString = ''; //Class Member variable public static Integer getCalculatedValue () { // Method definition and body // do some calculation myValue = myValue+10; return myValue; } }
Access Modifiers
Private
If you declare the access modifier as ‘Private’, then this class will be known only locally and you cannot access this class outside of that particular piece. By default, classes have this modifier.
Public
If you declare the class as ‘Public’ then this implies that this class is accessible to your organization and your defined namespace. Normally, most of the Apex classes are defined with this keyword.
Global
If you declare the class as ‘global’ then this will be accessible by all apex codes irrespective of your organization. If you have method defined with web service keyword, then you must declare the containing class with global keyword.
Sharing Modes
Let us now discuss the different modes of sharing.
With Sharing
This is a special feature of Apex Classes in Salesforce. When a class is specified with ‘With Sharing’ keyword then it has following implications: When the class will get executed, it will respect the User’s access settings and profile permission. Suppose, User’s action has triggered the record update for 30 records, but user has access to only 20 records and 10 records are not accessible. Then, if the class is performing the action to update the records, only 20 records will be updated to which the user has access and rest of 10 records will not be updated. This is also called as the User mode.
Without Sharing
Even if the User does not have access to 10 records out of 30, all the 30 records will be updated as the Class is running in the System mode, i.e., it has been defined with Without Sharing keyword. This is called the System Mode.
Virtual
If you use the ‘virtual’ keyword, then it indicates that this class can be extended and overrides are allowed. If the methods need to be overridden, then the classes should be declared with the virtual keyword.
Abstract
If you declare the class as ‘abstract’, then it will only contain the signature of method and not the actual implementation.
Class Variables
Syntax
[public | private | protected | global] [final] [static] data_type variable_name [= value]
In the above syntax ā
- Variable data type and variable name are mandatory
- Access modifiers and value are optional.
Example
public static final Integer myvalue;
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.
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.
The fun does not just end with photographs with our Dehradun Call Girl Service, and it is a new beginning in your life that you will achieve the ultimate quality of enjoyment. We have covered the entire areas of Dehradun, so that each person can be met sexually. We train them with expertise in various covert tricks to create the grand mood of any male. Our distinguished clients are particularly cheerful to see new conflicts and developments in sexual relationships.