APEX, Development

[ART-008] APEX Development Rules Basics


APEX is a development language similar to JAVA, that is used to build advanced automation in Salesforce Platform. As any of other language out in the world, some guidelines and code conventions has to be followed in order to build high quality applications.


Guidelines

As a former Java developer, I will stick to the code conventions for the Java programming language that you can find here, quite old but still a must know. Another point is that everything should be written in English, from code comments to method and class names following Camel Case. Some can find this very questionable, but from my point of view, software must be fully in English for the good and the bad that it will bring :D.

Class Header

A class must have a header at the top of it. It should be bring a description on the purpose of the class and useful information for every other developers to understand what is developed and how. Every time there is a huge modification on the behavior of the class, it should be mentioned in the header.

/**
 * @author FirstName LastName
 * @date dd/MM/yyyy - Creation
 * @date dd/MM/yyyy - author : Modification for XXX
 * @description ClassName – Functionalities description
 */

Some could find useless to specify the author as it can change very often and it’s not some information we can rely on to ask the how and the why as many could have work on the class. This kind of information can also be found and be more reliable on a GIT repository. But, I will continue to stick with this approach to have a quick overview and a guideline that will be shared across the entire project. Moreover, it will be very useful if you want to generate an ApexDoc.

Method Header

Every method must have header explaining the purpose of the method and bring information on every input and output.

/**
 * @author FirstName LastName
 * @date dd/MM/yyyy
 * @description Describe the functionality (tag the user modifying the method and why)
 * @param param1Name Description of the parameter
 * @param param2Name Description of the parameter
 * @throws ExceptionName Description
 * @return returnType Description of the returned element
 */

Code Line Comments

It’s crucial to have code line comments to have a good maintainability over the entire application, which will help developer to understand quickly what is done and communicate on any constraints or workarounds that he may have used to overcome a particular situation (Design, Governor limits …). Generally, code should be understandable without a need to massively comment every thing. Class name, method name, variable name, code structure should be explicit and so you that you only need to comment what is really matters, no comment for comments.

//User Trigram_Date_[artfXXXXX] PUT HERE YOUR LINE COMMENT BEFORE THE CODE WITH THE ARTIFACT NUMBER,  IN  LOWERCASE
for (Integer i=0; i<10; i++){...}

Formatting

NumberRule
1Indentation: 4 spaces or tabulation
2Method naming: Should be verbs in case sensitive with first letter in lowercase and each first letter of each new word in uppercase
3Variable naming: Should be in case sensitive with first letter in lowercase and each first letter of each new word in uppercase
4Constants: All letters in uppercase, each word is separated by underscore
5Brackets: Should be at the end of the first line ‘{‘ and in dedicated line ‘}’
public with sharing class MyExample{
    public static final String MY_CONSTANT_EXAMPLE = 'Example';

    public static String getMyExample(Integer nbVotes){
        String myExample = 'Example 2';
        
        if (nbVotes > 1){
            return myExample;
        }

        return MY_CONSTANT_EXAMPLE;
    }
}

Keep in mind that the number of characters allowed for apex coding is limited, so you should optimize the way you write your code as well as the naming of each component while keeping them intelligible.

Visualforce

NumberRule
1<APEX:MESSAGES> is the component to use to display messages in visualforce pages
2Do not code your picklist value in visualforce pages, prefer using controller to implement them
3Javascript and CSS should be static resources in order to use the caching capabilities
4Use transient variable in controller if they are not used between each server call, it will improve performance by reducing the view state size
5Use <apex:repeat> to iterate over a large collection
6Use cache attribute within <apex:page> component to benefit from CDN caching capabilities

Hard-coding

Hard-coding is strictly prohibited. There are variables that are independent from your org setting and other that are dependent of. Common issues that we can see is around Picklist values, URL, Profile name and Id, RecordType Name & Id … It exposes application to maintenance issues, duplication, and security breach.

NumberRule
1Move variable to static final constant in the top of the class
2Move variable to static final in dedicated class
3Move variable to Custom Setting or CustomMetadataType to handle mapping, org specific data, URL, date or range parameters …
4Use Custom Permission and Feature Management capabilities to replace profile name & id or other stuff to control the access
5Implement dedicated utility class to handle Schema and RecordType
6Use Named Credential to handle url endpoint and security

Unit Test

Unit testing must prove that code is behaving the way it has been designed in a functional and technical perspective.

NumberRule
1It must be governor limits proof
2The test should run without failure in each sandbox (dev,int,uat,preprod) before going to production
3Missing unit tests have to be written, no workaround is allowed
4A development is done only if the corresponding unit test has been written correctly
5Unit test must be isolated and not be org dependent, (seeAllData=true) is prohibited
6Always set the goal to 100% coverage (well to be honest it is mostly between 85% and 95% depending on many constraints)
7Every class and method should be covered independently at 100%, do not rely on cascading effects
8There must be many assertions to test functionalities for happy path and bad path

Remember that in order to deploy your components to production, the global coverage must be at least 75%, global means:

  • The global coverage of you current production is at least at 75%
  • The global coverage should rise to reach 100% and never decrease, nor go below 75%
  • The coverage of triggers must rise to 100% and never be less than 1%
  • The coverage of process builder and flows must rise to 100% and never be less than 75%
  • When deploying, the coverage is only calculated for the component inside

Error Handling

Error handling must be part of every development. It implies sometime to have a framework to handle generic situations or a case by case resolving. It should allow total or partial rollback, to alert to users, automatic replay, to store error in a table or field for post treatment.

The 2 main objectives of error handling are:

  • Ensure that database will always stay in a coherent state while errors are occurring during a transaction
  • Ensure there is a simple safe way to proceed “recover on error” by storing error details and giving a way to relaunch the process

Hiding an exception is also prohibited, better let the exception to be fired and propagated automatically or manually, here are 2 bad practices that we often see:

//Silent catching of exception without handling
try {
    something
}catch(Exception e){
}

//Silent catching of exception with useless system.debug
try {
    something
}catch(Exception e){
    System.debug('## APxxx '+ e.getMessage()+ ', Error :=' + e.getTypeName());
}

The first one can make error undetectable and can put database in an unexpected state as the transaction will continue “without errors”. The second one is only detectable if you track the user, but it’s like searching a needle in a haystack.

As a best practice, I will recommend you to:

  • Use savepoint to rollback to a coherent state
  • Use a framework to log errors in database or external system for post treatment
  • Monitor your batch process that can be prone to errors because of data volume
  • Implement a replay system when you deal with Webservice calls in your transaction as the webservice call cannot be rollback easily. Replay can be total or partial, you have to handle the step from which it has to be done

I will try to cover all these in another article, so just be patient :).

Principal Rules

NumberRule
1No value or Id must be hard-coded
2No SOQL, SOSL, DML, @future inside loop
3Unit test must be written for every class, every method, every use cases. Assertions should test many happy path and bad path. Unit test should be run with test user against at least 200 records.
4Class and method naming should follow camel case and not contain any special characters. Class must start with first letter in uppercase and method must start with lowercase
5Always check size, null value when dealing with collections
6Never write twice the same code, use dedicated class/method to reuse code
7Batch, trigger, webservice, controllers are logic less and are meant to route information, logic has to be develop in dedicated class
8Use Id of record to redirect to page, use relative url
9Use Id of record when dealing with CRUD operations in visualforce pages
10Comment carefully the code with class and method header and also code line comment
11Each method must be bulkified, the design should handle collection of records
12Do not mix SObject type in DML operations, 1 DML = 1 SObject type
13DML operations should be clearly identifiable, method should be written to return a collection of records and the DML should be outside of the method
14English is the default language to write code and comments
15System.debug and loglevel should be used precisely and not wisely

Conclusion

The objectives of this article is to give you an overview of the basics, some articles have already covered some points, other articles will cover the remaining points in details, just wait for it.

Hope you enjoy reading this article, see you soon for the next one ...

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.