It is important to have documented coding standards and naming conventions when developing software on the Force.com platform. It is not just useful for large codebases or team development environments. Small projects or even single developer codebases can benefit as well. This article outlines some benefits of standards and describes how to get started with and evolve standards. Finally, a set of naming conventions for Apex is outlined.
Following well documented coding standards has many benefits. I’ve detailed some of them below.
The codebase is easier to navigate since it has predictability. This helps with maintenance and new developer training. A sound naming convention is particularly useful for Apex since there is nothing like Java packages to organize the codebase.
Standards make code reviews simpler and less subjective. There’s no debating whether the code is up to par with best practices when the best practices are documented as the well-defined standards. Additionally, code reviews themselves are more efficient since less time can be spent on issues of formatting, etc., since the developer should have already adhered to the documented standards in their code under review.
It makes developers more efficient by taking “little” decisions off their plate. Instead of having to think about how something should be formatted or what something should be named they can just follow the standards and focus their thinking on solving the larger problems.
Automation can be used. IDEs like MavensMate support templates that allow developers to create common constructs (e.g., Apex unit test classes, Apex batch classes, etc.) that adhere to the defined standards. For example, if the codebase has a documented structure for a unit test class a template can be created for that basic structure. When a developer wants to create a unit test class, they create their class from the template and begin with the basic structure already completed.
Getting started with standardizing and evolving standards requires research and discipline.
A set of coding standards (e.g., formatting, logging, error handling) should be defined and a set of naming conventions for code artifacts (e.g., Apex classes, Visualforce pages, components, etc.) should be defined. It is also useful to define standards for the declarative / non-code components such as naming conventions for objects, fields, email templates, etc.
The Apex Developer’s Guide has a paragraph on naming conventions that suggests following the Java guidelines (Interestingly, Oracle doesn’t seem to have that page any more). Don’t reinvent the wheel. Do the research. Search for standards for other languages that are close to Apex like C# and Java. Look at standards that have been set for popular open source projects. Define a set of standards that make sense and are easy to follow. Google has a Java coding standards guide that has a thorough section on code formatting which is great as a base for Apex code formatting standards.
There are different ways to document standards. It is a good idea to not just rely on something like a Word document. A wiki platform (e.g., Confluence) is a much better option if possible. Look for one that at least supports user accounts, history tracking with diff capabilities, and access control mechanisms.
Once standards have been defined, don’t be afraid to make changes if it makes sense; however, don’t make knee-jerk hasty changes. Have a process for reviewing proposed changes and restrict modification permissions to the standards documentation to one or a select few. When new features come out, figure out if they fit in to the documented standards or if additions need to be made.
Example Naming Conventions
Below is a set of naming conventions that could be used for Apex and Visualforce code artifacts. It does not outline code standards such as formatting, method naming, etc. The recurring theme is that classes that work together appear near each other in class listings which makes it easier to know and find related functionality in the codebase. All classes should begin with an upper case letter.
In an org there may be many different classes and groups of classes functioning independently or as a group in an app (not AppExchnage app, to be clear). Prefixing all code artifacts that are used in an app will help to group them together. For example you might have a custom event registration app (prefix with Event or Evt), a custom planning app (prefix with Plan), a custom pricing app (prefix with Price or Prc). If you are developing code in a managed package you may not want to use a prefix strategy as your code will get installed in target orgs with a namespace prefix and your entire managed package likely is the app. I’ve left out the prefix in the following sections as it may or may not apply.
Unit Test Classes
Example: AccountControllerExtTest, ContactLabelControllerExtTest, SecurityUtilsTest
A benefit of adding Test as a suffix to denote a unit test class is that the unit test class will appear next to the class it is testing. Another common standard is to prefix all unit test classes with Test_. I see it as more of a benefit to use the suffix so that the test class appears next to the class it is testing.
Controllers and Visualforce
- <sObject><descriptive>ControllerExt – for a controller extension
- <descriptive>Controller – for standard controllers
- <sObject><descriptive> – for a Visualforce page that uses a standard controller. If there is a single controller extension being used the descriptive should be the same for the page and the controller.
Examples: Classes – AccountStdControllerExt, ContactLabelControllerlExt, AuditController. Pages – accountStd, contactLabel, audit.
A benefit of this is that all of the controller extensions for a certain object will appear near each other in class listings. Also, it is intuitive that an sObject’s controller extension would start with its name (easy to remember).
- <descriptive> – for the interface itself
- <descriptive><implementation descriptive> – for implementations
Examples: Interface – MapService. Implementers – MapServiceBase, MapServiceGoogle, MapServiceBing, MapServiceMapQuest.
An advantage to this structure is that all of the classes will appear next to each other in class listings. it’s easy to see/find all of the implementers of an interface. Additionally if there are other classes related to the functionality (e.g., MapRequest) they will appear close as well. This type of inverted naming works for Apex because it does not have package structures like Java. It does make the implementers’ names less natural sounding (e.g., “This class is a MapServiceGoolge” vs. “This class is a GoogleMapService”). If Apex did have package structures like Java, I would recommend not inverting the naming of the implementers (e.g., use GoogleMapService instead of MapServiceGoogle). Since Apex does not have that, the inverted naming is preferable to me.
Another common standard is to prefix interfaces with the capital letter “I” to indicate that they are an interface. That is very helpful in languages that don’t clearly differentiate between extending a class and implementing an interface; however, Apex does. To me, it is slightly more awkward and less natural to read and talk about interfaces using that convention. Your mileage may vary.
Scheduled and Batch Apex Classes
Examples: CartCleanupScheduler, CartCleanupBatch
An advantage is that the batch class is grouped next to the scheduler it uses. Note that with the introduction of dynamic type creation, using Type.forName patterns such as Wes Nolte’s Universal Batch Scheduler can reduce the need for as many Scheduler classes, so batch classes that need to be scheduled may not have a dedicated scheduler class. Still, if there is an interface or other classes related to the functionality (e.g., CartCleanupService), they will appear near the Batch.
Triggers and Trigger Handlers
Examples: AccountTrigger, AccountTriggerHandler
It is intuitive that an sObject’s trigger and trigger handler would begin with its name. An sObject should only have a single Trigger that delegates all work to a class or classes. Depending on the framework that is implemented, there may be a single class that handles all logic or there could be multiple classes involved like in Hari Krishnan’s excellent framework. In every case, the Trigger itself should never have business logic and should always call to some class to handle all business logic.
Examples: PageUtils, LogUtils, StringUtils
Utility classes group like functions into a class that can be used in many different areas. Utility classes typically only consist of static methods and are not instantiated. Using the suffix Utils underscores that the class is basically representing a collection of useful utility functions.
Examples: AccountWrapper, OpportunityWrapper, CaseWrapper
An advantage is that the wrapper appears next to any controller extensions with which it may be used.
- <descriptive> – That is all.
Examples: MapLocationRequest, MapLocationResponse
Again, an advantage is that the value object will appear near any other classes related to its functionality (e.g., MapService, MapServiceGoogle, MapServiceBing, etc.). Another common standard is to add the suffix VO for value object or on other platforms (e.g., JavaEE) the suffix DTO for data transfer object. Like the prefix “I” for interfaces, I find using a suffix here is slightly more awkward to read and talk about than not having it. Again, your mileage may vary.
There may be other categories of classes in your org such as services, domain objects, plugins, managers, processors, validators, etc. Be consistent in the naming of similar functioning classes. For example, don’t name one validator class AccountValidator and another OpportunityRuleChecker. If possible, define an interface and write your code to refer to the interface.
Standards are a very important part of software development and are beneficial in many ways. This article detailed a few very good benefits of following defined standards, but there are certainly more. Please feel free to comment with or link to any standards you have found useful for coding on the Force.com platform.