Defensive Apex Programming in Salesforce!!!

Defensive Apex Programming in Salesforce!!!

Defensive Apex Programming is a set of best practices and techniques for writing Apex code that is resilient to unexpected events and errors. It is a way of writing code that anticipates and handles potential problems before they cause outages or data loss.

Why do we need defensive programming?

  • To make the code behave as expected in unexpected situations.
  • Let the code monitor itself.
  • Improved code reliability.
  • Handling errors gracefully.
  • More performant, and secure code.


Let's take a look at some examples of how the code behaves if it is in and not in defensive mode.

Disclaimer: The following example I have added is just for demonstration purposes only??


Example 1 : Making Future Calls

Wrong way of making Future Calls - Not Defensive ?

public void callFuture(){

     futureMethod();
}

//Future Apex Class
@future
public static void futureMethod(){
    //business logic goes here
}        

Problems may arise with the above approach,

  1. What if another apex class calls the callFuture() method in a future context? Error: You cannot call one future in another future method and cannot do future chaining.
  2. What if the Batch class calls the callFuture() method? Error: You cannot call a method that is calling a future context method.
  3. What if another apex class runs in the future context and it may lead to hitting future governor limits...right?

Defensive way of making Future Calls - Defensive ?

public void callFuture(){
    if(System.isFuture() || System.isBatch())
       {
        regularCall();
       } 
    else {
        if(Limits.getFutureCalls() < Limits.getLimitFutureCalls()){
            doFutureCall();
        } 
        else {
            // log the message to understand why future call is denied
        }
    }
}


//Future Apex Class
@future
public static void doFutureCall(){
    regularCall();
}

public static void regularCall(){
    //business logic goes here
}        

With the above approach, future calls are handled properly and you get to know if it fails.

Example 2 : DML Operations

Improper way of handling DMLs - Not Defensive ?

Insert accList;        

Problems may arise with the above approach,

  1. If any error happens while inserting the records from the List, the complete transactions will be rolled back.
  2. There is no error handling mechanism to log the errors properly.


A proper way of handling DMLs - Defensive ?

Database.SaveResult[] srList = Database.insert(accList, false);

for (Database.SaveResult sr : srList) {
    if (sr.isSuccess()) {
        System.debug('Successfully inserted account ::: Account ID: ' + sr.getId());
    }

    else {               
        for(Database.Error err : sr.getErrors()) {                   
            System.debug(err.getStatusCode() + ': ' + err.getMessage());
            System.debug('Account fields that affected this error: ' + err.getFields());
        }
    }
}        

With the above approach, you are handling DMLs properly and errors gracefully.

Other Options: Use Try, catch, final blocks; Custom Exceptions to handle the errors properly.

Summary: Make your code more defective in order to be resilient, robust, secure, monitor themselves and withstand any kind of unexpected situations.

P.S: More Lines of Code with a defensive approach > minimal code with a defect ??


Credits & Inspired from: DAN APPLEMAN (https://www.salesforce.com/video/193789/#:~:text=Have%20you%20ever%20finished%20writing,you%20need%20to%20program%20defensively.)


Happy Trailblazing!!!


要查看或添加评论,请登录

社区洞察

其他会员也浏览了