I've looked in the Apex developer's guide and a saw the Naming Conventions section which has basically only has this:
We recommend following Java standards for naming, that is, classes start with a capital letter, methods start with a lowercase verb, and variable names should be meaningful.
I'm looking for something more in depth, such as end all Controllers with Controller and their tests with ControllerTest, etc.
What is a good set of naming conventions to use when developing on the Force.com platofrm? It would be preferable if the answer has something that handles custom objects, classes, visualforce pages, and components and not just Apex classes.
Attribution to: Peter Knolle
Possible Suggestion/Solution #1
Update on 2016-02-17
I've evolved the below in a few cases:
For collections, I always make the Collection
variable
plural, and I don't append the Collection Type as a suffix. Examples:Set<String> cities
instead ofSet<String> citySet
List<Employee__c> employees
instead ofList<Employee> employeeList
- (Infrequently Used)
Map<Id, Contact> contacts
instead ofMap<Id, Contact> contactMap
I use the Array notation for all
Lists
unless contructing a new List from an existing List or Set. This makes it easier to use the Auto-Complete in MavensMate which uses Sublime Text. (Plus it's less characters to type.) Examples:Account[] accounts
instead ofList<Account> accounts
Contact[] contacts = new Contact[]{}
instead ofList<Contact> contacts = new List<Contact>();
Integer[] sizes = new Integer[]{2, 3, 4, 5};
instead ofList<Integer> sizes = new List<Integer>{2, 3, 4, 5};
- But you have to use the prior convention if you want to initialize a
List
with an existing List or Set.Set<String> lastNames; String[] lastNameList = new List<String>(lastNames);
Abandoned the whole Return Variable mumbo jumbo. I always try to be as explicit as possible when using variable names. Example:
- If you have a getter
String getName()
, somewhere in the Method, you should set a String calledname
and return it at the end. Don't call the variablen
or something other than what the getter is explicitly called. public Data getExtraData(){ ... Data extraData = new Data(); ... return extraData; }
- If you have a getter
Original
To add to the mix:
Variable Names
For variables names, I like to have them be as explicit as possible usually adding the variable Type as a suffix unless the term is "understood". I especially favor long, descriptive names over short, sometimes-ambiguous names.
For instance variables & all methods, I start the name with a lower-case letter. For static variables I like to start the name with a Capital letter.
Additionally, whenever referencing static variables or methods, I ALWAYS add the class prefix. Furthermore, whenever referencing instance variables or methods, I try to use the this
prefix. Therefore it is much clearer where variables/methods come from/reside -- which is especially useful when copying code to and from other classes or re-writing code.
Examples:
Set<Id> contactIdSet
List<String> nameList
List<String> otherNameList
Decimal paymentAmount
Account parentAccount
When creating a Map
, I like to add a comment that states the key/values for reference.
Map<String, Account> accountMap = new Map<String, Account>(); // accountMap: clientCode ---> Account
for(Account clientAccount :
[SELECT Id, Client_Code__c
FROM Account
WHERE RecordType.Name = 'Client']
){
accountMap.put(clientAccount.Client_Code__c, clientAccount);
}
For for
loops, I favor using temp
as a prefix for already used variable names:
List<Tax_Payment__c> taxPaymentList = [SELECT Id, Amount__c, Payment_Date__c
FROM Tax_Payment__c
WHERE Payment_Date__c = THIS_FISCAL_QUARTER];
Map<Date, List<Tax_Payment__c>> taxPaymentMap = new Map<Date, List<Tax_Payment__c>>();
// taxPaymentMap: paymentDate ---> List<TaxPayment>
for(Tax_Payment__c taxPayment :taxPaymentList){
List<Tax_Payment__c> tempTaxPaymentList = taxPaymentMap.get(taxPayment.Payment_Date__c);
if(tempTaxPaymentList == null)
tempTaxPaymentList = new List<Tax_Payment__c>();
tempTaxPaymentList.add(taxPayment);
taxPaymentMap.put(taxPayment.Payment_Date__c, tempTaxPaymentList);
}
Rewriting the last example using static and instance methods:
public class TaxPaymentExtension{
public static String DefaultTaxType = 'Federal 941';
String taxType;
public List<Tax_Payment__c> taxPaymentList {get;set;}
public Map<Date, Tax_Payment__c> taxPaymentMap {get;set;}
public TaxPaymentExtension(){
this.taxType = ApexPages.currentPage().getParameters().get('taxtype');
if(String.isBlank(this.taxType))
this.taxType = TaxPaymentExtension.DefaultTaxType;
this.taxPaymentList = [SELECT Id, Amount__c, Payment_Date__c
FROM Tax_Payment__c
WHERE Payment_Date__c = THIS_FISCAL_QUARTER
AND Tax_Type__c = :taxtype];
this.taxPaymentMap = TaxPaymentExtension.getPaymentMap(taxPaymentList);
}
public static Map<Date, Tax_Payment__c> getPaymentMap(List<Tax_Payment__c> tpList){
Map<Date, Tax_Payment__c> returnMap = new Map<Date, List<Tax_Payment__c>>();
// taxPaymentMap: paymentDate ---> List<TaxPayment>
for(Tax_Payment__c taxPayment :taxPaymentList){
List<Tax_Payment__c> tempTaxPaymentList = taxPaymentMap.get(taxPayment.Payment_Date__c);
if(tempTaxPaymentList == null)
tempTaxPaymentList = new List<Tax_Payment__c>();
tempTaxPaymentList.add(taxPayment);
taxPaymentMap.put(taxPayment.Payment_Date__c, tempTaxPaymentList);
}
}
For methods returning a value I like to (1) always create the return variable at the start of the method and (2) have the return variable name of the form return
+ Type:
!!!! This is all mumbo jumbo. See Update on 2016-02-17 above. !!!
public List<Case> getCaseList(){
List<Case> returnList = new List<Case>();
// ...
return returnList;
}
public String getActivityFile(Date startDate, Date endDate){
String returnString = '';
// ...
return returnString;
}
public class Data {
public List<String> nameList {get;set;}
public Map<String, Decimal> amountMap {get;set;} // amountMap: name ---> amount
}
public Data getData(){
Data returnData = new Data();
// ...
return returnData;
}
Test Classes
For Test Classes I like to always construct all necessary Test Data in a subClass. This way it is easy to create the Test Data in the Test Class itself as well as any other Test Class that might need to use it now or later on.
I also like to test Instance and Static methods separately:
@isTest
public class SpecialCaseExtensionTest{
public class TestData{
Account testAccount {get;set;}
List<Case> caseList {get;set;}
TestData(){
// ...
}
// Have multiple constructors for multiple scenarios
TestData(Integer caseCount){
// ...
}
}
@isTest
public static void testInstanceMethods(){
TestData tData = new TestData();
Test.startTest();
// ...
Test.stopTest();
}
@isTest
public static void testStaticMethods(){
TestData tData = new TestData();
Test.startTest();
// ...
Test.stopTest();
}
}
....
@isTest
public class AnotherCaseExtension{
public TestData{
SpecialCaseExtensionTest.TestData specialTestData {get;set;}
List<Account> extraAccountList {get;set;}
// ...
}
@isTest
public static void testInstanceMethods(){
TestData tData = new TestData();
Test.startTest();
// ...
Test.stopTest();
}
@isTest
public static void testStaticMethods(){
SpecialCaseExtensionTest.TestData tData = new SpecialCaseExtensionTest.TestData();
// All I need is the Special Case Extension Test Data!
Test.startTest();
// ...
Test.stopTest();
}
Attribution to: Scott Pelak
Possible Suggestion/Solution #2
Follow the CamelCase Java conventions, except for VF pages and components start with a lower case letter.
Triggers:
- <ObjectName>Trigger - The trigger itself. One per object.
- <ObjectName>TriggerHandler - Class that handles all functionality of the trigger
- <ObjectName>TriggerTest
Controllers:
- <ClassName>Controller
- <ClassName>ControllerExt
- <ClassName>ControllerTest
- <ClassName>ControllerExtTest
Classes:
- <ClassName>
- <ClassName>Test (These might be Util classes or Service classes or something else).
Visualforce pages and components:
- <ControllerClassName>[optionalDescription] (without the suffix Controller). There might be multiple views so could also have an extra description suffix.
Object Names and custom Fields
- Upper_Case_With_Underscores
Variables/properties/methods in Apex
- camelCaseLikeJava - more easily differentiated from fields
Test methods in test classes
- test<methodOrFunctionalityUnderTest><ShortTestCaseDesc> - For example, testSaveOpportunityRequiredFieldsMissing, testSaveOpportunityRequiredFieldsPresent, etc.
Working on something that would be used as an app or in some cases just a project? If yes, then do the following:
Prefix all custom objects, apex classes, Visualforce pages and components with an abbreviation so that they are easier to identify (e.g., easier for changesets). For example the WidgetFactory app would have the prefix wf on those. Additionally, when adding custom fields to a standard object they would also be prefixed to identify them as part of the app/package.
The main reason for the Object and Fields Names using Upper_Case_With_Underscores is that when you type in the name field or object with spaces it automatically adds the underscores. Although Apex is case insensitive, always refer to the Objects and Custom Fields in the code as Upper_Case_With_Underscores as well for consistency all around and consistency with what is generated by the SOQL schema browser and other tools. Object and Field Labels (which are generally ignored by code but visible to users) should keep spaces, not underscores.
Attribution to: Peter Knolle
Possible Suggestion/Solution #3
I generally subscribe to the following rules:
Apex Classes
- For a generic class, I just prefix with a capital
C
, e.g.CSomeClass
- For those which are test classes I use
CTest
as the prefix - For a Visualforce controller I use the prefix
CVFC
which means they're all grouped together
Visualforce Pages
- I tend to use
VFP
as a prefix, maybe redundant but it helps keep them together when there are pages from other sources involved
Triggers
- Here, I use the object type followed by an underscore and the trigger type, e.g.
Contact_AfterUpdate
,Lead_BeforeInsertUpdateDelete
If I'm working with code that all logically sits together in psuedo-package (or a real package) then I tend to also prefix everything with a suitable abbreviation.
Attribution to: Matt Lacey
Possible Suggestion/Solution #4
For the class naming, I follow Separation of Concerns Principle (https://trailhead.salesforce.com/en/content/learn/modules/apex_patterns_sl/apex_patterns_sl_soc)
For the method and variable naming,I have write it down in my article here: https://github.com/Xixiao007/Apex-Best-Practices/blob/master/content/meaningful_names.md
Attribution to: Xi Xiao
Possible Suggestion/Solution #5
Besides Salesforce.com specific naming recommendations you can and should keep to the Standard Java Naming conventions.
We recently started an Open Source repo on GitHub porting the famous Java Static code analyzer PMD to Apex. We also ported many of the original Java rules from PMD to Apex. Especially the Java Naming rules can be applied without any changes to Apex.
The latest PMD SNAPSHOT release also contains an updated Eclipse plugin. Just point your Force.com IDE to this Update site: https://sourceforge.net/projects/pmd/files/pmd-eclipse/update-site-latest/ and run 16 configurable Apex rules on your code.
Attribution to: Robert Sösemann
Possible Suggestion/Solution #6
The best and most complete documentation I've found about SalesForce conventions is provided by the CFPB "Consumer Financial Protection Bureau", which is basically a US Government organisation.
https://github.com/cfpb/salesforce-docs/blob/master/_pages/Salesforce-Naming-Conventions.md
Unfortunately, due to the length of this document, I don't think it is wise to copy/paste it here, as it should be. I'm therefore just taking a few screenshots of what I believe is the most important/interesting convention rules.
I also wonder if SalesForce provides any tooling that allows administrators to automatically enforce such guidelines. But I'll open another question for that.
Another resource, that is very focused on APEX conventions is https://github.com/anupj/Apex-Code-Convention/blob/master/ApexCoding.txt
Attribution to: Vadorequest
This content is remixed from stackoverflow or stackexchange. Please visit https://salesforce.stackexchange.com/questions/890