- The Purpose of Coding Standards
- Java and .NET
- Sample Java Coding Standards
Sample Java Coding Standards
The remainder of this article provides a detailed sample of coding standards for a fictional company called The Open Company. See my previous articles in this series for other sources that can help you in your quest to implement coding standards.
NOTE
I hope that The Open Company is fictional. Although I think it would be a great name for a company, I couldn't find any record of a company with that name, and the URL doesn't appear to be taken! If there is any company of that name, please dissociate this article from anything to do with that company.
Overview of Technical and Applications Architecture
The Open Company has the following applications architecture (see Figure 1) to which all its applications and web sites must adhere. Note that the Client Tier corresponds to the View in the MVC design pattern, the Web Tier corresponds to the Controller, and the Business Tier corresponds to the Model. Any Controller aspects of applications (for example, event handlers that call server-side functionality) will exist within the Client Tier for applications.
Figure 1 Applications architecture for The Open Company.
The database used within The Open Company is Oracle 9. Wherever possible, stored procedures should be used in preference to SQL.
The Oracle JDBC driver should be used to manage database connections to Oracle.
The J2EE server used is BEA WebLogic 7.
Client-side functionality within applications should use Java Swing 1.1.
The CDE/MOTIF look-and-feel should be used for applications.
Which Language Is Used for Which Purpose?
It should be clear from Figure 1 that the following components should be written in the following languages/technologies:
Client Tier: HTML or Java using Swing 1.1
Web Tier: JSP pages only
Business Tier: Enterprise Java Beans (EJB) 2.0 only
EIS Tier: Oracle 9 only (SQL or stored procedures [preferred])
Which Object Type Is Used for Which Purpose?
Where an application is to be used only internally to The Open Company, it should be developed using Java rather than HTML in the Client Tier if any of the following conditions are met:
Security/authentication is required.
Frequent access to internal databases is required.
Lots of reference data needs to be downloaded to the client.
Otherwise, the application should be developed using HTML in the Client Tier.
JSP pages should contain only code that checks/validates input from the client and then redirects to other JSP pages, redirects to other HTML pages, or makes calls to Enterprise Java Beans. Enterprise Java Beans should be used to do the following:
Provide a service to the application using Stateless Session Beans (for example, price lookup, given a product ID)
Manage status within a session using Stateful Session Beans (for example, shopping cart)
Update the database entity to store persistent changes using Entity Beans (for example, call the UpdateStockLevel() method on the widget Entity Bean)
Naming of Namespaces
Package names should start with the reverse URL of the company:
com.companyname
For example:
com.theopencompany
Reusable/common code should be stored within the common subdirectory:
com.companyname.common
For example:
com.theopencompany.common
Each project (application) should have its own subdirectory structure:
com.companyname.projectname
For example:
com.theopencompany.widgetshop
Each project should also have a common subdirectory, for code that is common within that project only:
com.companyname.projectname.common
For example:
com.theopencompany.widgetshop.common
Make sure that the correct common code goes into the correct subdirectory.
Each EJB bean within the project should have its own subdirectory structure within the project:
com.companyname.projectname.ejbname
For example:
com.theopencompany.widgetshop.widget
EJB files should be named as follows, where SLB is used for Stateless Session Beans, SFB for Stateful Session Beans, and EB is used for Entity Beans.
For the bean:
com.theopencompany.projectname.ejbname.ejb.[SLB|SFB|EB]ejbnameEJB
For example:
com.theopencompany.widgetshop.widget.ejb.EBwidgetEJB
For the remote interface:
com.theopencompany.projectname.ejbname.ejb.[SLB|SFB|EB]ejbname
For example:
com.theopencompany.widgetshop.widget.ejb.EBwidget
For the home interface:
com.theopencompany.projectname.ejbname.ejb.[SLB|SFB|EB]ejbnameHome
For example:
com.theopencompany.widgetshop.widget.ejb.EBwidgetHome
Exception: Session beans should be named as follows if the session simply wraps an entity pattern.
For the bean:
com.companyname.projectname.ejbname.manager.[SLB|SFB|EB]ejbnameEJB
For example:
com.theopencompany.widgetshop.widget.manager.EBwidgetEJB
For the remote interface:
com.companyname.projectname.ejbname.manager.[SLB|SFB|EB]ejbname
For example:
com.theopencompany.widgetshop.widget.manager.EBwidget
For the home interface:
com.companyname.projectname.ejbname.manager.[SLB|SFB|EB]ejbnameHome
For example:
com.theopencompany.widgetshop.widget.manager.EBwidgetHome
For JNDI purposes, beans should be named as follows:
[SLB|SFB|EB]ejbnameEJB
For example:
EBwidgetEJB
Formatting Source Code
The general principles for formatting source code are designed to make the source code as easily readable as possible. Remember that 80% of the effort expended on any development project is in maintenance, and in an average of 60% of maintenance work, the original developer is not the person who maintains the code.
CAUTION
It's imperative that comments also take into account all Javadoc requirements. If a Javadoc requirement overrides any of the rules below, the Javadoc requirement takes precedence.
Indenting
The opening slash (/) in the comment at the top of a Java file should be in character position 4. The code below this comment should start in the next character position (5) so that it lines up with the first asterisk (*) in the comment. All indents after this point should be 4 characters deep.
Indents are required after each opening brace ({) and are terminated immediately before the closing brace:
public Image getImage(URL url, String name) { try { return getImage(new URL(url, name)); } catch (MalformedURLException e) { return null; } }
Braces
The opening brace ({) should be placed at the end of the line immediately preceding the block of code it contains. The closing brace (}) should be the only character on the line following the block of code it contains, and should be placed in line with the preceding block of code; that is, its position should be reduced by one (as shown in the example above).
Wrapping Lines
When an expression will not fit on a single line, break it according to these general principles (derived from Sun's coding guidelines):
Break after a comma.
Break before an operator.
Prefer higher-level breaks to lower-level breaks.
Align the new line with the beginning of the expression at the same level on the previous line.
If the above rules lead to confusing code or to code that's squished up against the right margin, just indent 8 spaces instead.
Here are some examples of breaking method calls:
someMethod(longExpression1, longExpression2, longExpression3, longExpression4, longExpression5); var = someMethod1(longExpression1, someMethod2(longExpression2, longExpression3));
Following are two examples of breaking an arithmetic expression. The first is preferred because the break occurs outside the parenthesized expression, which is at a higher level.
longName1 = longName2 * (longName3 + longName4 - longName5) + 4 * longname6; // PREFER longName1 = longName2 * (longName3 + longName4 - longName5) + 4 * longname6; // AVOID
Following are two examples of indenting method declarations. The first is the conventional case. The second would shift the second and third lines to the far right if it used conventional indenting, so instead it indents only 8 spaces.
//CONVENTIONAL INDENTING someMethod(int anArg, Object anotherArg, String yetAnotherArg, Object andStillAnother) { ... } //INDENT 8 SPACES TO AVOID VERY DEEP INDENTS private static synchronized horkingLongMethodName(int anArg, Object anotherArg, String yetAnotherArg, Object andStillAnother) { ... }
Line wrapping for if statements should generally use the 8-space rule because conventional (4 space) indentation makes seeing the body difficult. For example:
//DON'T USE THIS INDENTING STYLE if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { //BAD WRAPS doSomethingAboutIt(); //MAKE THIS LINE EASY TO MISS } //USE THIS INDENTING STYLE INSTEAD if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { doSomethingAboutIt(); } //OR USE THIS STYLE if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { doSomethingAboutIt(); }
Here are three acceptable ways to format ternary expressions:
alpha = (aLongBooleanExpression) ? beta : gamma; alpha = (aLongBooleanExpression) ? beta : gamma; alpha = (aLongBooleanExpression) ? beta : gamma;
General Layout
Class and interface declarations should be laid out in the order set down by Sun, as shown in the following table:
|
Part of Class/Interface Declaration |
Notes |
1 |
Class/interface documentation comment (/**...*/) |
See "Documentation Comments" for information on what should be in this comment. |
2 |
class or interface statement |
|
3 |
Class/interface implementation comment (/*...*/), if necessary |
This comment should contain any class-wide or interface-wide information that wasn't appropriate for the class/interface documentation comment. |
4 |
Class (static) variables |
First the public class variables, then the protected, then package level (no access modifier), and then the private. |
5 |
Instance variables |
First public, then protected, then package level (no access modifier), and then private. |
6 |
Constructors |
|
7 |
Methods |
These methods should be grouped by functionality rather than by scope or accessibility. For example, a private class method can be in between two public instance methods. The goal is to make reading and understanding the code easier. |
Commenting
In general, see the Javadoc guidelines for information on how to format comments. Detailed here are any exceptions to the Javadoc guidelines.
Comments must start with /**. Although not mandatory for Javadoc 1.4, at The Open Company, all subsequent comment lines should commence with an asterisk (*), followed by a space unless it is the final line in the comment, in which case the line should contain only */ (see the example below).
/** * Returns an Image object that can then be painted on the screen. * The url argument must specify an absolute {@link URL}. The name * argument is a specifier that is relative to the url argument. * <p> * This method always returns immediately, whether or not the * image exists. When this applet attempts to draw the image on * the screen, the data will be loaded. The graphics primitives * that draw the image will incrementally paint on the screen. * * @param url an absolute URL giving the base location of the image * name the location of the image, relative to the url argument * @return the image at the specified URL * @see Image */ public Image getImage(URL url, String name) { try { return getImage(new URL(url, name)); } catch (MalformedURLException e) { return null; } }
Note that the first line in the comment should be a short summary (less than 30 words if at all possible) of what the method does, as it will be placed in the method summary table and index.
It is mandatory within The Open Company that all code be checked using Doc Check prior to being checked into the System Test, User Acceptance Test, or Live repositories.
Naming of Components/Variables/Properties
A consistent naming pattern is one of the most important elements of predictability and discoverability in a managed class library. Widespread use and understanding of these naming guidelines should eliminate many of the most common user questions. This topic provides naming guidelines for The Open Company. For each type, you should also take note of some general rules with respect to capitalization styles, case sensitivity, and word choice.
Capitalization Styles
The capitalization styles to use for different identifiers are listed below.
NOTE
See this web page for an explanation of camel case, Pascal case, and so on.
Pascal case: Method names, class names, property names, exception class names, interface names, event names
Camel case: Parameters, variable names
Lowercase: Package names
NOTE
Namespaces in .NET use Pascal case, so package naming is out of step with the equivalent for .NET, but this is necessary and unavoidable.
Case Sensitivity
To ensure cross-language, cross-platform operation, do not use names that require case sensitivity; that is, never create two components, files, directories, properties, methods, or variables that differ only by case within the same context.
Constants
Constants should be fully capitalized with underscores (_) separating words. For example:
static final int MIN_WIDTH = 4;
Types
Class names do not have a prefix. They should be nouns, should have simple and descriptive names, and should use Pascal case.
For parameters and variable names, Hungarian type prefixes should not be used, as in a heterogeneous environment these parameters may come in from external sources where the types don't match. Use names that describe the parameter's meaning rather than its type. Use camel case. Do not start variables with a dollar sign ($) or underscore (_), even though both are technically correct.
Property/member variable names should not employ Hungarian type prefixes. Use names that describe the property's meaning rather than its type. Use Pascal case.
Naming of Functions/Methods
Method names do not have a prefix. They should be verbs, should not contain the noun to which they apply, and should use Pascal case.
Naming of Files/Directories
Package names should use all lowercase (and therefore so should the directories corresponding to these packages). See the section "Naming of Namespaces" above.
File extensions should follow the standards laid out by Sun:
Java source: .java
Java bytecode: .class
JSP page: .jsp
JSP fragment: .jspf
Tag library descriptor: .tld
Naming of (Security) Roles
Objects that will exist within LDAP (or LDAP-like repositories such as Active Directory) should conform to the following naming conventions, adapted from Microsoft's object naming guidelines for LDAP/Active Directory.
Objects are located within LDAP domains according to a hierarchical path, which includes the labels of the LDAP domain name and each level of container objects. The full path to the object is defined by the distinguished name (also known as a DN). The name of the object itself, separate from the path to the object, is defined by the relative distinguished name.
The distinguished name is unambiguous (identifies one object only) and unique (no other object in the directory has this name). By using the full path to an object, including the object name and all parent objects to the root of the domain, the distinguished name uniquely and unambiguously identifies an object within a domain hierarchy. It contains sufficient information for an LDAP client to retrieve the object's information from the directory.
For example, a user named James Smith works in the marketing department of a company as a promotions coordinator. Therefore, his user account is created in an organizational unit (OU) that stores the accounts for marketing department employees who are engaged in promotional activities. James Smith's user identifier is JSmith, and he works in the North American branch of the company. The root domain of the company is reskit.com, and the local domain is noam.reskit.com. The diagram in Figure 2 illustrates the components that make up the distinguished name of the user object JSmith in the noam.reskit.com domain.
Figure 2 Distinguished name for the user object JSmith. (Courtesy Microsoft Corporation.)
Look-and-Feel/GUI Design
The CDE/MOTIF look-and-feel should be used for applications.
Source Code Control
CVS (on top of RCS) will be used within The Open Company. For information on how to use this system, see the CVS-RCS HOWTO.
The Source Code Manager has ownership of the source code control system and any questions can be directed to him/her.
A different branch will exist at the project level within CVS for each release of a project's code; for the release that is currently under development, this will be subdivided into development, test, uat (user acceptance test), and live.
The development tree will correspond to the version of code currently residing on the development web server, the test tree to the version on the test server, and so on.
Bugzilla will be used for bug/defect tracking.
Portability Issues
If any of the guidelines in this document cause issues with portability of code, the guidelines should be changed to deal with the portability issue more effectively.
At the time of writing, it is understood that these guidelines are designed to enable portability between different platforms using Java, and to make it easier to convert the Java code to .NET code should the need arise.
Localization/Internationalization Issues
All localization code should be stored under the common directory/package in a subdirectory called localizationeither the global common directory or the project common directory as is appropriate to the specific code.
Every registered user of any application/project should have a profile record in the profile table detailing localization preference; this can be used to present the most applicable localized front end to the user.
Detailed information about localization issues within The Open Company can be found in internal technical architecture documentation.
Documenting Changes/Change Logs
A change-control process is detailed in the internal standards documentation.
Bugzilla will be used for bug/defect tracking.
Code reviews by the Source Code Manager for the project will check the following:
Filename naming conventions
Package/directory structure
Configuration files/registry keys needed
Any database changes required by the code
Before any code is checked in for the first time and before it is checked back in after changes are made, it must be
Commented
Logged in the Change Management log/Defect log
Labeled/versioned as appropriate
Unit tested
Standard Error-Handling
Common error-handling code used by all applications within The Open Company is to be found in the common directory for the company, and any common error-handling that is specific to an application/project is to be found under the project common directory.
In general, all JSP files must have an errorPage setting in a page directive. Following are the guidelines for writing error-handling code:
Write your Bean (or other component) so that it throws certain exceptions under certain conditions.
Use a simple tracking mechanism in your component to help you gather information about what the user was doing when the exception was thrown. (If you move into developing J2EE applications, your application will be able to save state, which is a better way of providing information.)
In the JSP file, use a page directive with errorPage set to the name of a JSP file that will display a message to the user when an exception occurs.
Write an error page file, using a page directive with isErrorPage="true".
In the error page file, use the exception object to get information about the exception.
Use informative messages, either in your error page file or included from other files, to give your user an informative message relevant to what he or she was doing when the exception was thrown.
Standard Session-Timeout Handling
Detailed guidelines on how to handle session timeouts using common code can be found in the technical architecture documentation for The Open Company. In the common directory for each application is code that handles session timeouts in a standard manner.
Standard Help Facilities
Each application/web page must have a link in the upper-right corner of the screen/page linking the user to the standard help page/screen for the current application. This standard help page/screen should provide some context-sensitive help on the right side of the page/screen and provide access to the index/glossary on the left side, with search facilities across the top of the page/screen. Standard code is available in the common directories to provide consistent help across all applications. See the technical architecture documentation for more information.
Configuration Information
Each registered user of an application has a profile record in the profile table. This table includes configuration information for that user, including localization information, personalization information, and so on.
Users who do not log in to use a web site/application are considered to be guest users and do not have access to personalization/localization features until they are registered.
Configuration information about hardware, web servers, application servers, and so on can be found in the technical architecture documentation.