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
Number | Rule |
---|---|
1 | Indentation: 4 spaces or tabulation |
2 | Method naming: Should be verbs in case sensitive with first letter in lowercase and each first letter of each new word in uppercase |
3 | Variable naming: Should be in case sensitive with first letter in lowercase and each first letter of each new word in uppercase |
4 | Constants: All letters in uppercase, each word is separated by underscore |
5 | Brackets: 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
Number | Rule |
---|---|
1 | <APEX:MESSAGES> is the component to use to display messages in visualforce pages |
2 | Do not code your picklist value in visualforce pages, prefer using controller to implement them |
3 | Javascript and CSS should be static resources in order to use the caching capabilities |
4 | Use transient variable in controller if they are not used between each server call, it will improve performance by reducing the view state size |
5 | Use <apex:repeat> to iterate over a large collection |
6 | Use 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.
Number | Rule |
---|---|
1 | Move variable to static final constant in the top of the class |
2 | Move variable to static final in dedicated class |
3 | Move variable to Custom Setting or CustomMetadataType to handle mapping, org specific data, URL, date or range parameters … |
4 | Use Custom Permission and Feature Management capabilities to replace profile name & id or other stuff to control the access |
5 | Implement dedicated utility class to handle Schema and RecordType |
6 | Use 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.
Number | Rule |
---|---|
1 | It must be governor limits proof |
2 | The test should run without failure in each sandbox (dev,int,uat,preprod) before going to production |
3 | Missing unit tests have to be written, no workaround is allowed |
4 | A development is done only if the corresponding unit test has been written correctly |
5 | Unit test must be isolated and not be org dependent, (seeAllData=true) is prohibited |
6 | Always set the goal to 100% coverage (well to be honest it is mostly between 85% and 95% depending on many constraints) |
7 | Every class and method should be covered independently at 100%, do not rely on cascading effects |
8 | There 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
Number | Rule |
---|---|
1 | No value or Id must be hard-coded |
2 | No SOQL, SOSL, DML, @future inside loop |
3 | Unit 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. |
4 | Class 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 |
5 | Always check size, null value when dealing with collections |
6 | Never write twice the same code, use dedicated class/method to reuse code |
7 | Batch, trigger, webservice, controllers are logic less and are meant to route information, logic has to be develop in dedicated class |
8 | Use Id of record to redirect to page, use relative url |
9 | Use Id of record when dealing with CRUD operations in visualforce pages |
10 | Comment carefully the code with class and method header and also code line comment |
11 | Each method must be bulkified, the design should handle collection of records |
12 | Do not mix SObject type in DML operations, 1 DML = 1 SObject type |
13 | DML operations should be clearly identifiable, method should be written to return a collection of records and the DML should be outside of the method |
14 | English is the default language to write code and comments |
15 | System.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 ...