Friday, March 13, 2015

"Bulkify Your Code" - Explanation of Salesforce' Governor Limit with Use Case

Bulkify Your Code” – I am quite sure you have heard this phrase a lot, but do you really know what is the meaning of this phrase and why this one is so important?

This post is all about “Bulkify Your Code” where I will explain –
  • What is the meaning of this phrase?
  • Why this is so important?
  • Explain with Use Cases
So let’s start with What is the meaning of “Bulkify Your Code” –
If you want to combine repetitive tasks in your Apex classes/Triggers, you need to bulkify your code.
For example – if you are given a task to check whether a student’s score is greater than 80, you can’t write a code which can check score of single student. Rather your code should check score of n number of students.
So it means you need to repeat the same task of checking score for n number of students in your apex code and that is what called “Bulkify Your Code”

So now definitely the question that came to your mind – Why “Bulkify Your Code” is so important?
To explain the important, let me give you a real-life example. Say for example, you are staying in an apartment where along with your family, 100 other families are also staying. Each of these families (including your definitely) need water, right? To fulfil this requirement, what the owner will do is that he/she will install same size (I mean the same dimension) of pipes for each family to equally distribute the water.

Exactly the same concept applies for Salesforce. Salesforce’s in based on Multi-Tenant Architecture. So Salesforce needs to make sure that when you are running your piece of code, it should not hamper other’s piece of code (in terms of performance, availability of resources etc.) To explain in more details – Say Company A and Company B both are running their applications in Salesforce. Now at the particular time instance, Company A is running 1000 SOQL queries, whereas Company B is running only 5 queries. Definitely running 1000 queries will take more resources compared to 5 queries and as a result Company B will feel bad performance. Now Salesforce is a non-biased architecture (Yes, I use this term). So Salesforce will make sure Company A and Company B will get the same share. To achieve this Salesforce comes up with Governor Limit.

Governor Limit will make sure that as developer you are writing efficient and scalable code. Now why I love Salesforce a lot and why I call Salesforce a non-biased architecture, because even if you pay more to Salesforce, they will never increase the limit. The only workaround is to write efficient code. Superb. Salesforce rocks!!!!

Use Case:
I have the below two custom objects in my org with field details as per the below screenshot 
My requirement is that if an Airport record is having the Operational checkbox true, then create a country record where Country.Country Name = Airport.Country. Very simple right!!!
But this can lead to many problems.

So let's write the trigger for that first -
trigger AirportTrigger on Airport__c (after insert) {
    for(Airport__c anAirport : Trigger.new){
        if(anAirport.Operational__c){
            Country__c aCountry = new Country__c(
                                                Name=anAirport.Country__c
                                                );
            insert aCountry;
        }
    }
}

Very simple trigger. What the trigger is doing is simple iterating over Trigger.new (it is returning a list of Airport records that are getting inserted) and checking whether the Operational__c field is true or not. If true, then creating a new Country record with Country name same as airport's country name.

This trigger will work fine when you create a single airport record from Salesforce, because, in that case, Trigger.new will return you only 1 record and which will perform max 1 DML operation (when Operational__c is true). 

But the problem will occur when we will insert multiple airport records with import wizard. 

Now what I will do is that I will prepare a csv file with 1000 airport records in the below fashion.
Now if I try to import these 1000 airport records with import wizard, below is what I am getting -
Now when I checked the debug log, below is the error message I am getting -
Ok - got it!!. So we are getting the error "Too many DML statements". This is the Governor Limit set by Salesforce, which states as a developer you can execute at max 150 DML statements. But what we are doing is -

When we tried to import 1000 new airport records, Trigger.new did batch up mass insert upto 200 records at a time. Each of  these 200 records executed one new insert statement for Country object. So total number of DML operation becomes 200, which is beyond the Salesforce's Governor Limit (150 DML Operations). 

Now let's play more with Salesforce Governor Limit and change the import file like below -

As you can see here, I have changed Operational field alternatively. Now when I tried to import this file(File contains 1000 Airport records), below is what I am getting -
Success!! Do you know the reason for the success. Ok. Let me tell you. 

Trigger.new again did the batch up of mass insert upto 200 records at a timebut out of these 200 records, only 100 records were having Operational__c field set as true. So total number of DML operation were 100 which was within Salesforce's Governor Limit.

But still our code is not efficient as with this code, we can't insert 1000 records (our first csv files). So we have to make our code efficient and the way we can do that is -
trigger AirportTrigger on Airport__c (after insert) {
    List<Country__c> allCountries = new List<Country__c>();
    
    for(Airport__c anAirport : Trigger.new){
        if(anAirport.Operational__c){
            Country__c aCountry = new Country__c(
                                                Name=anAirport.Country__c
                                                );
            allCountries.add(aCountry);
        }
    }
    
    if(allCountries.size() > 0){
        Database.insert(allCountries);
    }
}
Now with the above code, when I tried to insert 1000 airport record with Operational__c field set to true for all, below is what I am getting -

Great!! So the code is now efficient and can handle any number of insert. The changes we did are as follows -

  • Created a list which will hold all the country records which need to be inserted into Salesforce org.
  • Finally if the size of the list is greater than 0, then execute Database.insert which will insert all the country records.
The advantage with this approach is that we are executing only 1 DML operation.

Hope this will help you to understand Salesforce's Governor Limit. Any question, please let me know. Thanks.

Please check my next post with another example - 
"Bulkify Your Code" - Another Example with Use Case

0 comments:

Post a Comment