20 Tips for Salesforce Developers

In this post we will talk about top 20 Tips for Salesforce Developers to keep in mind while writing the code. Salesforce developers should aware about Salesforce governor limits while writing the code. Here are some Concepts For Every New Salesforce Developer To Learn be become a master in Salesforce.

Top tips of Salesforce Developers

Here are top 20 tips of Salesforce Developers.

1. Do not hard code record Id in code

Do not hard-coded record Id in code: Never hard-coded recordId anywhere in code. RecordId varies for each org and can cause issues if hard coded in code logic.

2. Always check access before DML statements

Always check access before DML statements: It is always a good practice to check for the access level before executing any DML statement. For example,

Instead of the below:

Database.upsert(accountList); 

Use this:

if(Schema.SObjectType.Account.isCreateable() && Schema.SObjectType.Account.isUpdateable()){
        Database.upsert(accountList);
}

3. Check access while doing SOQL

Check access while doing SOQL: Similar to DML, we should use check access level in SOQL query in order to follow security best practices. We can make use of the WITH SECURITY_ENFORCED clause and stripInaccessible() method.

Instead of the below:

List<Account> accountList = [SELECT Name, Rating, Type FROM Account];

Use this:

List<Account> accountList = [SELECT Name, Rating, Type FROM Account WITH SECURITY_ENFORCED];

4. Be mindful of governor limits

Be mindful of governor limits: Always be careful of the governor limits in the code. The Limits class has a bunch of methods to check limits and we can make use of those in our code. One example is to limit the records in SOQL query based on the available no. of rows which can be retrieved.

List<Account> accountList = [SELECT Name, Rating, Type FROM Account LIMIT :(Limits.getLimitQueryRows()- Limits.getQueryRows())];

5. Be careful of NULL values

While calling any methods always check for NULL first. For example, in this case before checking whether the Account description contains particular text, we should check if it is NULL. Like this:

for(Account acc: accountList){
  if(acc.Description!=NULL && acc.Description.contains(‘Test’)){
    //some processing
  }
}

6. Optimize code by leveraging safe navigation operator

Optimize code by leveraging safe navigation operator: Use safe navigation operator to replace if-else checks and optimize your code. For example:

Instead of the below:

List<Account> accList = [SELECT Description FROM Account ORDER BY CreatedDate DESC LIMIT 1];

String substringValue;

if(!accList.isEmpty() && accList[0].Description !=NULL){
    
    substringValue= accList[0].Description.toUpperCase().
    
}

Use this:

List<Account> accList = [SELECT Description FROM Account ORDER BY CreatedDate DESC LIMIT 1];

String substringValue = accList?.get(0)?.Description?.toUpperCase();

7. Use String.isBlank() while checking for empty or NULL on string

Use String.isBlank() while checking for empty or NULL on string: Use String.isBlank() whenever checking for blanks since it works for whitespaces also. For example,

String s = ' ';
System.debug(String.isEmpty(s)); // false
System.debug(String.isBlank(s)); // true

8. Use SOQL for loops whenever possible

Use SOQL for loops whenever possible: Use SOQL for loops whenever possible. It not only saves the use of a collection for storing the result, it is also efficient as it processes the record using efficient chunking and by calling query and queryMore methods of the SOAP API. It also avoids the limit on heap size. For example,

Instead of the below:

List<Account> accList = [SELECT Name FROM Account LIMIT 10];

for(Account acc: accList){

    //some processing
}

Use this:

for(Account acc: [SELECT Name FROM Account LIMIT 10]){
    //some processing
}

9. Use map while storing the Ids from SOQL query

Use map while storing the Ids from SOQL query: While storing Ids from SOQL query, try to use map instead of iterating through the result set. For example, 

Instead of the below:

Set<Id> accountIds = new Set<Id>();

for(Account acc: [SELECT Name FROM Account WITH SECURITY_ENFORCED LIMIT 10]){
    
    accountIds.add(acc.Id);
}

Use this:

Map<Id, Account> accountMap = new Map<Id, Account>([SELECT Name FROM Account WITH SECURITY_ENFORCED LIMIT 10]);

10. Use a utility class for storing constant variables

Use a utility class for storing constant variables: Use a utility class for storing all the constants related to your project. It can be considered as a constant repository and enable us to reuse the constants across apex classes.

11. Implement error handling properly:

Implement error handling properly: Tracking the error is important to get the root cause of a malfunction in code. Use a separate object for storing the error details and insert a record in this object with the details of the error whenever the code breaks with some error.

12. Remove unnecessary debug

Remove unnecessary debug: Do not put any debug which is not required. If you are putting any debug statement for figuring out some error, ensure that is removed after the fix of the error.

13. Create test data in setup method

Create test data in setup method: As a best practice, try to create data only in the setup method and reuse the same across the test methods.

14. Use test data factory framework

Use test data factory framework: Use test data factory class to create data. This class is a special type of class which can be called from test methods and it contains generic version of the methods of creating test data, hence can be reused. The code in test data factory class does not count toward org code size limit.

15. Use Test.startTest() and Test.stopTest() to test the functionality

Use Test.startTest() and Test.stopTest() to test the functionality: Always wrap the code which contains the functionality you are testing inside Test.startTest() and Test.stopTest(). Test.startTest() creates a new set of Governor limits and it continues till Test.stopTest() is reached.

16. Always use assert to validate the expected and actual results

Always use assert to validate the expected and actual results: Use assert statements in test class. It is not about attaining higher coverage only, we should also need to ensure our test produces expected results.

17. Run test method using System.runAs()

Run test method using System.runAs(): Create user in test class and run test method in the context of that persona which is appropriate as per the business. This also ensures whether that persona is having necessary permissions to perform the functionality.

18. Test error scenario as well

Test error scenario as well: It is important to test negative scenarios as well in the test class. This will check whether our code breaks as per the expected setup and also additional errors can be tracked.

19. Use aura:if for conditional rendering

Use aura:if for conditional rendering: In aura component, if you need to show block of markup conditionally then use aura:if instead of using slds-hide. aura:if makes the component lightweight and loads it faster by deferring the creation of the enclosed element only when the condition is fulfilled to be true. But in case of slds-hide, the component is created upfront and it remains hidden.

20. Always use dynamic field import in LWC

Always use dynamic field import in LWC: If you are importing any custom field in LWC, always use dynamic import. Because static imports are not referenced during field deletion, but dynamic imports are referenced. For example

Instead of the below:

import { LightningElement, api, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';

const fields = ['CustomField1__c'];

export default class TestFieldAccess extends LightningElement {

    @api recordId;

    @wire(getRecord, { recordId: '$recordId', fields})
    accountRecord;

    get customFieldValue(){

        return getFieldValue(this.accountRecord.data, CUSTOM_FIELD1);
    }

}

Use this:

import { LightningElement, api, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
import CUSTOM_FIELD1 from '@salesforce/schema/Account.CustomField1__c';

const fields = [CUSTOM_FIELD1];

export default class TestFieldAccess extends LightningElement {

    @api recordId;

    @wire(getRecord, { recordId: '$recordId', fields})
    accountRecord;

    get customFieldValue(){

        return getFieldValue(this.accountRecord.data, CUSTOM_FIELD1);
    }

}

Summary

I hope this Apex Best Practices and top 20 tips for Salesforce Developers will help you to become a best Salesforce Developer in Salesforce ecosystem.

Abhishek Saha
Abhishek Saha

Salesforce Developer at Accenture | Trailhead Ranger

Articles: 5

Leave a Reply

Your email address will not be published. Required fields are marked *