I have been coding in Apex on and off for over 3 years and there are a few best practices that I have incorporated and a few that I try to incorporate when writing Apex code. There are a lot of good resources out there which you can refer to and this post derives content from my personal experience. If you ever take the Advanced Developer or Platform Developer II, it’s imperative that you follow these best practices. And if you are a technical architect or lead who does code reviews, checking for these best practices becomes all the more important. With that being said, I am assuming that you already have an understanding of Salesforce specific terms like ‘bulkification’ and ‘governor limits’ so let’s proceed with discussing their importance.
Respecting Governor Limits
This is one of the most important considerations when writing Apex code on the Force.com platform. Never place queries or DML statements inside a for loop. Use collection variables like Sets, Lists and Maps to perform bulk DML’s/queries. Since the maximum number of records that can be retrieved via a SOQl query is 50,000, put that SOQL query inside a for loop since that helps chnk the query results into batches of 200 records. Use WHERE and LIMIT keywords to filter records in SOQL queries whenever possible. Here’s a full list of Apex governor limits which must be considered when writing code:
Handling Trigger or Batch exceptions
As a developer, it is your responsibility to handle possible exceptions and deal with them gracefully within code. The end user should never see a raw error message resulting from your code and the goal should be to either use try catch blocks to catch unhandled exceptions and/or use addError() method to display user friendly messages to the end user. Here’s an excellent resource for reading about exception/error handling:
You could always create a custom object to store persistent logs for better debugging which would be immensely helpful when troubleshooting code related issues. I wrote a blog post about it a while ago:
Writing Readable code
Code should always be well indented and structured. There should be comments everywhere in the code; the more the better. When another developer or administrator reads through your code, he/she should be able to tell what your code’s intended purpose is. I recommend adding a short description before the code begins, for each method and its purpose and for lines of code where it makes sense to explain to the admin/dev what it’s doing.
Making Efficient Design decisions
Developing simple, modular and reusable code by having only one trigger per object and keeping the main logic outside of triggers and handling it within helper classes/methods, using Field Sets for Visualforce pages wherever possible, using Custom Labels, using Custom Settings and Custom metadata types for easy configuration and maintainability are some of the designs that must be considered when writing Apex.
Bulkifying your Code
Apex and Bulkification go hand in hand. If you think they don’t, that needs to change. Right now. Ensuring that DML or querying for records never happens inside the For loop is one of the best ways to avoid issues related to handling mass data manipulation. Every single helper method inside your class should be efficiently built to handle a bulk of records. Be it a single record, 200 records or a 1000 records; your code should be handle it all.
Achieving maximum Code Coverage
The aim should always be to achieve close to 100% code coverage and test for as many scenarios as possible. Even though Salesforce requires 75% code coverage as a prerequisite for deployment to Production, your goal should be to achieve as much code coverage as you possibly can.
Having a Data Utility class
Never ever rely on existing data in your Salesforce org and never use the @isTest(SeeAllData=true) annotation in your test classes. At no cost, should there be any environment dependency so make sure that you are creating data from scratch. I prefer creating a Data Utility class which is my source of all data needs for my unit tests.
Testing Large Data Volumes
Make sure that you are testing with bulk records in the test methods. This makes sure that your main logic is ‘bulkified’ and it wouldn’t fail when mass manipulating data in Salesforce.
Performing Meaningful Asserts
Assert, assert and assert. System.assert should be used generously when building test classes. Make sure that the asserts in test methods are not just checking for list sizes but for values of fields and expected page behavior. A lot of developers try to perform dummy code coverage by doing asserts on list size only or build classes with meaningless lines of code which should be discouraged. Are you checking for both positive and negative test cases? Are you asserting for exceptions? Are you testing boundary conditions and null values? These are the some of the questions that you must ask yourself when writing test methods.
Writing Optimal sized and Efficient test methods
Don’t squeeze in all test logic into one single test method. It is good practice to have a separate test method for testing a different business logic across multiple test methods in your test class. It makes your code more readable and easier to manage when running test methods and troubleshooting issues.
Your goal should always be to write efficient, optimal and scalable yet simple code. I admit that I am not able to follow all of the above best practices every single time I write code but I do try my level best to incorporate as many of these principles as possible. Here are a few other great resources that discuss such principles in more detail: