-
-
3.3. Do not use Hungarian notation or add any other type identification to identifiers.
-
3.7. *Remove blank spaces in the API name of custom field and custom object
-
3.9. Use a noun or a noun phrase to name a class, field, or property
-
3.10 Use a verb or a verbal phrase to name a method or trigger
-
3.17. Do not use letters that can be mistaken for digits, and vice versa
-
-
6.3. *An else sub-statement of an if statement shall not be an if statement without an else part.
-
6.5. *Do not make explicit comparisons to true or false, if we know the variable is not null
-
6.6. Do not access a modified object more than once in an expression
-
6.7. *Do not use selection statements (if, switch) instead of a simple assignment or initialization.
-
7. Object oriented programming
-
7.3. *Use a property rather than a method when the member is a logical data member.
-
7.4. *Use a method rather than a property when this is more appropriate
-
7.5. Do not create a constructor that does not yield a fully initialized object
-
7.6. *Use this and super keywords to do constructor chaining and avoid duplicate initialization.
-
-
8.2. *Only re-throw exceptions when you want to specialize the exception
-
8.3. *Always figure out a way to log that an exception is thrown.
-
8.9. *Avoid side-effects when throwing recoverable exceptions.
-
8.10. Do not throw an exception from inside an exception constructor.
-
8.11. *Do not throw an exception from inside a getter property
This coding standard is mandatory for Meginfo. The objective of this coding standard is to have a positive effect on
- Avoidance of errors/bugs, especially the hard-to-find ones.
- Maintainability, by promoting some proven design principles.
- Maintainability, by requiring or recommending a certain unity of style.
- Performance, by dissuading wasteful practices.
- Rules and recommendations are given that promote reliability and maintainability.
This standard pertains to the use of Apex language in Meginfo, and also contains following languages:
- C#
- Java
- JavaScript
- XML
- HTML
This standard does not include rules or recommendations on how to use the class libraries or APIs.
Many of the rules and recommendations were taken from the Coding Standard of Philips Medical Systems and the book Clean Code written by Robert Martin. They are for C# language. These rules and recommendations were taken here to make an agreement inside the company to keep the code and tags conform to a same standard. This standard describes the rules and recommendations mainly for Apex. But a considerable part of a coding standard could be considered for other languages, which is also described in this standard.
Each chapter contains a set of rules and/or recommendations. An entry started with an asterisk (*) is a recommendation.
A rule should be strictly followed, and be broken only for compelling reasons where no reasonable alternative can be found. Also let the author know why the rule should be broken then.
A recommendation should be followed unless there is good reason to do otherwise. Also, there are exceptions in some rules and recommendations. The exceptions demonstrated the scenario in which the rule/recommendation is not followed.
Terms | Description |
---|
|
Good reasons do not include personal preferences of style.
This coding standard gives you some room in choosing a certain style. Do keep the style consistent within a certain scope. This scope usually means to a salesforce organization or a project.
In Pascal casing the first letter of each word in an identifier is capitalized. For example, BackColor.
In Camel casing only the first letter of the second, third, etc. word in a name is capitalized; for example, backColor.
The table below provides the casing for the most common types.
IDENTIFIER | CASE | EXAMPLE |
---|---|---|
Class | Pascal | Account |
Enum type | Pascal | Severity |
Enum values | Pascal | Severity.Error |
Field | camel | listItem |
Final/Const field | Pascal | MaximumCount |
Static field | Pascal | RedValue |
Interface | Pascal | IDisposable |
Method in Apex, Java | camel | toString |
Method in C# | Pascal | ToString |
Parameter | camel | typeName |
Property | Pascal | BackColor |
Trigger | Pascal | SendEmailOnNewAccount |
In Apex, primitive types such as String, Decimal are all classes. So they should be Pascal casing.
Two-letter abbreviations in Pascal casing have both letters capitalized. In Camel casing this also holds true. With respect to capitalization in Pascal and Camel casing, abbreviations with more than two letters are treated as ordinary words. Please note, the abbreviation ID is often written as Id since it has become a wellknownordinary word, like UserName is written as Username.
Some examples:
CAMEL CASING | PASCAL CASING |
---|---|
newImage | NewImage |
urlAddress | UrlAddress |
uiEntry | UIEntry |
id | Id |
pmsMR | PmsMR |
Hungarian notation means to put the variable type prior to its name. For example: strName, intAge. Use of Hungarian notation is deprecated by companies like Microsoft because it introduces a programming language-dependency and complicates maintenance activities.
Apex is case-insensitive, so do not define type called name and Name in the same context.
Exception
It is allowed in C# to have identifiers that differ only in case in distinct categories, e.g. a property BackColor that wraps the field backColor.
Do not contract words in identifiers, but do use well-known abbreviations. For example, do not use GetWin instead of GetWindow, but do use a well-known abbreviation such as UI instead of UserInterface. Some examples:
RIGHT | WRONG |
---|---|
opp | oppo, op, oppt, oppty |
Avoid using underscore (_) in identifiers. It is deprecated in most companies.
Exception
In Apex, underscores exist in the name of every custom field and custom object as “__c” or “__r”, and in managed package. When you create custom field/object, remove the blank spaces in the name to avoid unnecessary underscores. In other words, blank spaces could appear in the label, but not in the name.
Some examples in Apex,
LABEL | API NAME |
---|---|
Person Email | PersonEmail__c |
Email Notification | EmailNotification |
As described in the example of section 3.6, blank spaces are allowed in the label of custom field or custom object; and NOT allowed in its API name.
Name an identifier according to its meaning and not its type. Every identifier should be meaningful.
Avoid using language specific terminology in names of identifiers. As an example, suppose you have a number of overloaded methods to write data types into a stream. Do not use definitions like:
void write(Double doubleValue); // wrong
void write(Long longValue); // wrong
Instead, use:
void write(Double value);
void write(Long value);
Also, every identifier should be meaningful. Consider you have a method receives 3 parameters, do not define it like:
void calculate(Decimal a, Decimal b, Decimal c); // wrong
Instead, please use:
void calculate(Decimal length, Decimal width, Decimal height);
Furthermore:
Integer d; // wrong; what it stands for?
Integer daysSinceCreation; // right; clearly enough now
theList.add(x); // wrong; what included in the List?
if (a1[i] == a2[i]) // wrong; we can tell no different between a1 and a2
If we have the following 3 members defined in a class, who can tell the difference?
// Example with ambiguous naming
getActiveAccount();
getActiveAccounts();
getActiveAccountInfo();
Exception
Only a few variables can be meaningless. For example, the variable in a for loop:
for(Integer i = 0; i < max; i++)
Or the conventional name for a special variable:
Graphics g; // g is a common name for Graphic instance in Java
Classes, fields and properties should be noun phrases.
Also, if the class involved is a derived class, it is a good practice to use a compound name. For example, if you have a class named Button, deriving from this class result in a class named RoundCorneredButton.
The name for a Visualforce page can either be a noun or verb phrase.
Methods and Triggers do actions, so they should be verbal phrases.
Avoid naming a trigger something like AccountTrigger. Trigger name should be meaningful, as well as verbal.
The name for a Visualforce page can either be a noun or verb phrase.
Some people like to put “m” prior to the member fields in a class, like:
private String m_age; // wrong
private String mAge; // wrong
private String _age; // wrong
However, this is deprecated.
In general, a method in which it is difficult to distinguish local variables from member fields is too big.
See also in section 3.3.
A valid trigger name should be meaningful, and without a Trigger suffix. For example,
trigger AccountTrigger on Account(after insert) // wrong
trigger SendEmailOnNewAccount on Account(after insert) // right
Classes derived from Exception are special. They should have a suffix Exception. For example, DmlException.
Custom controller or extensions for Visualforce pages should have a suffix Controller.
For example, EmailNotificationController
For example, do not name an enumeration type Protocols but name it Protocol instead. Consider the following example in which only one option is allowed.
public enum Protocol
{
Tcp,
Udp,
Http,
Ftp
}
To create obfuscated code, use very short, meaningless names formed from the letters O, o, l, I and the digits 0 and 1. Anyone reading code like
Boolean b001 = (lo == 10) ? (I1 == l1) : (lol != l01); // wrong
Will marvel at your creativity.
See also in section 3.8.
Do not use something like accountList to name a variable of type List. Please use a plural noun to name a collection, for example, accounts.
Do not use this keyword to dereference members. The use of this is only allowed as a reference to the current class instanc or to prevent name clashing between method parameters and class fields.
Example:
void setName(String name)
{
this.name = name;
}
The header block must containing the purpose of this class/trigger.
/*
* Controller of page EmailNotification
* Sends email to ……
*/
public class EmailNotificationController
Use // instead of /* */ if the comments is a single line.
Conventionally, comments are of singular form in third person. But the identifiers are not.
For example:
// Gets a string represents the name of the student.
public String getStudentName();
// Sets the name of the student
public String setStudentName(String value);
For example, everybody knows that is a default constructor:
public class Whatever
{
// default constructor
public Whatever()
{
…
}
}
Any variable/method that is important to the class, or is difficult to understand, should be commented to help others understand the logic.
Blank lines are treated equal as comments. Use them to separate class members. For example, each method should be separated by a blank line. If a method contains more than one operation, separate them with blank lines. Do remove unnecessary blank lines in your code.
For some reason, we need to comment some lines out when coding. Please remember to remove them before deploy them to production.
Consider the following section of code:
// Check to see if the user is eligible for full benefits
if ((user.flags & HOURLY_FLAG) && (user.age > 65))
The comment is sufficient, but why not write like this:
if (user.isEligibleForFullBenefits())
// or
if (isEligibleForFullBenefits(user))
Avoid the C style where all variables have to be defined at the beginning of a block, but rather define and initialize each variable at the point where it is needed.
Avoid the C style where all variables have to be defined at the beginning of a block, but rather define and initialize each variable at the point where it is needed.
Making it final/const ensures that memory is allocated for that item only once.
private final Integer maxCount = 100;
Exception
If the value of a constant field must be calculated at run-time, use a static field instead.
For example, consider a Color class that expresses a certain color internally as red, green, and blue components, and this class has a constructor taking 3 numeric values, then this class may expose several predefined colors like this.
public class Color
{
public static Color Red = new Color(255, 0, 0);
public static Color Black = new Color(0, 0, 0);
public static Color White = new Color(255, 255, 255);
public Color(Integer r, Integer g, Integer b)
{
// implementation
}
}
Repeating a name that already occurs in an outer scope is seldom intended and may be surprising in maintenance, although the behavior is well-defined.
Integer foo = something;
…
if(whatever)
{
double foo = 12.34; // do not re-use this name
}
Exception
Some methods have a parameter of the same name as a field. For example, a construction like this.foo = foo;
Updating the loop variable within the loop body is generally considered confusing, even more so if the loop variable is modified in more than one place.
All flow control primitives (if, else, while, for, do, switch) shall be followed by a block, even if it is empty.
Please note that this also avoids possible confusion in statements of the form:
if(b1) if(b2) Foo(); else Bar(); // which ‘if’ goes with the ‘else’?
The intention of this rule is to define a “default action” after all the prior conditions are missed. Consider the following example.
void Foo(String answer)
{
if (answer == “no”)
{
System.debug(“You answered with No”);
}
else if (answer == “yes”)
{
System.debug(“You answered with Yes”);
}
else
{
// This block is required, even though you might not care of any other
// answers than “yes” and “no”.
}
}
One entry, one exit is a sound principle and keeps control flow simple. However, if some cases, such as when preconditions are checked, it may be good practice to exit a method immediately when a certain precondition is not met.
It is usually bad style to compare a bool-type expression to true or false. However, every type in Apex is an object, includes Boolean. This means the default value of a bool-type variable is null not false.
The best practice to do this is to give a meaningful name to the variable and initialize with a default value. Then we can use the bool-type directly in conditional statements.
Example:
Boolean isFailed = false;
try
{
insert accounts;
}
catch(Excecption ex)
{
isFailed = true;
ApexPage.addMessages(ex); // error handling
}
if(isFailed)
{
// process with the failure
}
In above example, do not compare the isFailed variable with true or false:
if(isFailed == true) // not wrong, but not recommended either
if(isFailed != false) // absolutely wrong
If we have to make explicit comparison, compare it with “== true”.
BOOL test
Take the following code as an example:
v[i] = ++i; // wrong
v[i] = ++c; // right
i = ++i + 1; // wrong and useless; i += 2 would be clearer
i = i + 1; // right
Express your intentions directly. For example, rather than
Boolean pos;
If(val > 0)
{
pos = true;
}
else
{
pos = false;
}
Or (slightly better)
Boolean pos = (val > 0) ? true : false;
Or even better
Boolean pos = (val > 0);
This rule is accepted in most companies.
Exception
Static fields and const fields, which may have any accessibility deemed appropriate, may be an exception.
Properties should be stateless with respect to other properties, i.e. there should not be an observable difference between first setting property A and then B and its reverse.
In some cases a method is better than a property:
- The operation is a conversion, such as Object.toString()
- The operation is expensive enough that you want to communicate to the user that they should consider caching the result.
- Obtaining a property value using the get accessor would have an observable side effect.
- Calling the member twice in succession produces different results.
- The order of execution is important. See section 7.2.3.
- The member is static but returns a value that can be changed.
- The member returns a copy of an internal array or other reference type.
- Only a set accessor would be supplied. Write-only properties tend to be confusing.
Only create constructors that construct objects that are fully initialized. There shall be no need to set additional properties. A private constructor is exempt from this rule.
Classes with more than one constructor are common. Pick one constructor as a main; others shall invoke the main constructor.
Also applies to the derived classes.
Consider the following example:
public virtual class Student
{
private String name;
private Integer age;
private String email;
public Student(String name)
{
this.name = name;
}
public Student(String name, Integer age)
{
this(name);
this.age = age;
}
public Student(String name, Integer age, String email)
{
this(name, age);
this.email = email;
}
}
public class CollegeStudent extends Student
{
private String major;
public CollegeStudent(String name, Integer age, String email, String major)
{
super(name, age, email);
this.major = major;
}
}
Avoid creating triggers or classes that contains too many lines. It’s not only difficult to read, but also hard to maintain.
A class contains too many lines should be considered to separate into a couple of small classes.
A trigger contains too many lines should be considered to put some code into a class.
This standard does not set any explicit limit on the length of a source file, thus leaving the definition of “too big” to groups or projects.
Also, avoid creating a method that contains too many lines. A method contains too many lines should be considered to separate into a couple of small methods.
This recommendation is not part of the standard strictly. It’s about a good habit to write the code. Some developers used to write almost everything into the class constructor. For example:
// An example with bad code
public class Example
{
public Example()
{
List<Contact> contacts = [select …… from Contact where …..];
if(contacts.size() > 0)
{
Student = contacts[0];
}
// and more initializations
}
public Contact Student { get; set; }
…
}
When there are more properties to initialize, the constructor becomes extremely fat and hard to read. A design principle is to postpone the initialization to where they are about to be used:
// An example with good code
public class Example
{
public Example()
{
// nothing to initialize here.
}
public Contact Student
{
get
{
List<Contact> contacts = [select …… from Contact where …..];
if (contacts.size() > 0)
{
return contacts[0];
}
return null;
}
}
…
}
The reasons why this is better:
- The constructor contains less code, so that easier to read.
- The logic to pull student only exists inside the student property.
However, this introduced a drawback of more SOQL count. For a frequently retrieved property, we should wrap a field.
// An example with good code
public class Example
{
private Contact theStudent;
public Example()
{
// nothing to initialize here.
}
public Contact Student
{
get
{
if(theStudent == null)
{
List<Contact> contacts = [select …… from Contact where …..];
if (contacts.size() > 0)
{
theStudent = contacts[0];
}
}
return theStudent;
}
}
…
}
Do not throw exceptions in situations that are normal or expected (e.g. end-offile). Use return values or status enumerations instead. In general, try to design classes that do not throw exceptions in the normal flow of control. However, do throw exceptions that a user is not allowed to catch when a situation occurs that may indicate a design error in the way our class is used.
Only catch and re-throw exceptions if you want to add additional information and/or change the type of the exception into a more specific exception. In the latter case, set the
Exceptions cannot be swallowed without any warning, except few situations, e.g. FormatException on data conversion and the default value is specified.
There should always be a solution to warn users that an exception has ever occurred. Solutions include but not limited to:
- Show up to the end user as error message (ApexPages.addMessage method)
- Email notification
- Write to a log object
- Alert in Javascript
For example, consider a communication layout that will throw an Invalid OperationException when an attempt is made to call Send() when no connection is available. To allow preventing such a situation, provide a property such as Connected to allow the caller to determine if a connection is available before attempting an operation.
If you use an explicit data conversion, always ensures that the source type can be converted to the destination type, so that an exception is not occurred. To verify if a class is a specific type of class, use the instanceOf keyword. This rule also applies to the conversion methods in Apex, includes but not limited to:
- DateTime.parse
- Integer.valueOf
- Decimal.valueOf
- String.valueOf
The methods above should be nested in a try/catch block.
Consider the following code:
User currentUser = [select SchoolName__c from User where
Id =:UserInfo.getUserId() limit 1];
String schoolName = currentUser.SchoolName.replace(‘_’, ‘ ‘);
A null pointer exception would possibly happen.
DO remember to correct as below:
User currentUser = [select SchoolName__c from User where
Id =:UserInfo.getUserId() limit 1];
String schoolName = (currentUser.SchoolName == null) ? ‘’ :
currentUser.SchoolName.replace(‘_’, ‘ ‘);
When you instantiate a new exception, set its Message property to a descriptive message that will help the caller to diagnose the problem. For example, if an argument was incorrect, indicate which argument was the cause of the problem.
Also mention the name (if available) of the object involved. Also, if you design a new exception class, note that it is possible to add custom properties that can provide additional details to the caller.
Do not throw a generic exception if a more specific one is available(related to 8.2.5).
For example, if during the process of adding a new item to a list, an exception is raised, then the caller may safely assume that the item has not been added, and another attempt to re-add it is possible.
This doesn’t make sense.
Throwing an exception from inside a getter property is not recommended. But in few situations, this is possible. Any exceptions from property should be careful.
Use an enum type instead of String if the variable has only a few values. This enhances clarity and type-safety. Try to avoid casting between enumerated types and integral types.
Consider the constructor of ApexPage.Message class. When initializing, we specify an ApexPage.Severity enum instead of a string.
new Message(Severity.Fatal) // right; Severity is a predefined collection.
new Message(“Fatal”) // wrong
In this way, typos can be avoided, and users can have more precise control to the values.
Do not use literal values, either numeric or strings, in your code other than to define symbolic constants. Use the following pattern to define constants:
public class Whatever
{
public static Color White = new Color(255, 255, 255);
public static final Integer MaxNumber = 19;
public static final String PersonAccountRecordTypeId = ‘016x00000036y’;
public static final String FinanceProfileId = ‘0350000039x’;
}
A common mistake is to hard-code record type id or profile id. Instead, we should use predefined constant variables (as shown above).
Exception:
The value 0, 1, and null can nearly always be used safely. Very ofen the values 2 and -1 are OK as well. String or number in test methods are exempt from this rule. Literals are allowed then their meaning is clear from the context, and not subject to future changes.
avg = (a + b) / 2; // right; clear enough
milliSeconds = seconds * 1000; // right; clear enough
If the value of one constant depends on the value of another, do attempt to make this explicit in the code, so do not write
public final Integer MaxItem = 32;
public final Integer MaxHeight = 64; // wrong as it is calculated from MaxItem
public final Integer MaxHeight = MaxItem * 2; // right
Please note that an enum can often be used for certain types of symbolic constants.
Most floating-point values have no exact binary representation and have a limited precision.
Exception:
When a floating-point variable is explicitly initialized with a value such as 1.0 or 0.0, and then checked for a change at a later stage, that makes sense.
For example, do not cast a long to an integer, unless you can guarantee that the value of long is small enough to fit in the integer.
Actions in the page controller or extension should always return PageReference as a return value. This rule guarantees a method looks like a page action. If you don’t want the page to be redirected, please specify return null at the end of the method.
Java developers used to put the opening brace in the same line of the block definition, like:
public class Whatever {
// not recommended
}
This is not about right or wrong, but we make an agreement to put it to the next line, like:
public class Whatever
{
// recommended
}
This rule applies to all kinds of code blocks, includes class, method, property, if else,while, etc.
Use blank spaces properly as betrayed in the following table:
EXPRESSION | BLANK SPACE | EXAMPLE |
---|---|---|
Arithmetical operator | 1 | b + c |
Assignment | 1 | a = b + c |
Comparison | 1 | a >= b + c |
Semi-colon | 0 | a = b + c; |
if/while | 1 | if (a == b + c) |
for loop | - | for (i = 0; i < 100; i++) |
Unary operator | 0 | !bool -i |
Increment/Decrement | 0 | i++ --i |
Ternary operator | 1 | (a == null) ? 0 : a |
Function call | 0 | sendEmail(email); |
Subscript | 0 | array[0] |
Automatic property | 1 | String Name { get; set; } |
Example:
a=b+c; // wrong
a = b + c ; // wrong
a = b + c; // right
a = (a == null)?0:a; // wrong
a = (a == null) ? 0 : a; // right
for(i=0;i<10;i++) // wrong
for (i = 0; i < 10; i ++) // wrong
for (i = 0; i < 10; i++) // right
a = -- b; // wrong
a = --c; // right
a = - b; // wrong
a = -b; // right
public String Name{get;set;} // wrong
public String Name { get; set; } // right
Note: unary, increment and decrement operators are an exception.
For example:
@isTest
testMethod static void testThisClass() // NOT recommended
static void testThisClass() // recommended
People have different favor to type the SOQL statement. Somebody likes to start a newline to put each field.
This standard recommends put SOQL statement into one line. For some extra long SOQL statement, you could choose to put thesub-select/from/where clause to a new line. Nevertheless, align the clauses properly.
For camel casing, see section 3.2.
This means the format of the document should be carefully maintained includes blank space indent ending tags etc.
Example:
<apex:page showHeader="false" sidebar="false" title="abcd">
<apex:stylesheet value="{!URLFOR($Resource.Skin2, 'css/About.css')}" />
<apex:composition template="{!$Site.Template}">
<apex:define name="content">
<c:AboutNav />
<div class="rightTextCon">
<img class="ourStoryPic" alt="About The Juno Company, Juno Baby, Juno Jr." src="{!URLFOR($Resource.Skin2_Images, 'ourStoryPic.png')}" />
<div class="rightText">
<span class="shadowText">test</span><br />
<span class="shadowText">test</span><br />
</div>
</div>
</apex:define>
</apex:composition>
</apex:page>
Though we are not writing XHTML document, its standard should also get respected. For example, following attribute are required according to XHTML standard.
ATTRIBUTE | EXAMPLE |
---|---|
alt in img | <img src="" alt="" /> |
Because Apex runs in a multitenant environment, the Apex runtime engine strictly enforces a number of limits to ensure that runaway Apex does not monopolize shared resource. Refer to document: http://wiki.developerforce.com/page/Governors_in_Apex_Code