Collab Software Coding Standards Guide for Java
Based on:
NETSCAPE'S SOFTWARE CODING STANDARDS GUIDE FOR JAVA
Christie Badeaux, Technology Evangelist
INTRODUCTION
As part of our renewed interest and need to write good java code, the
following guide for creating java code was developed. Most of the
data here came from the above mentioned source. Some modifications
were made to more clearly reflect the Collab team's needs. These
standards will be used in code reviews and should be referred to when creating
code.
GOALS OF THESE STANDARDS
First of all there is the need to recognize the purpose of these guidelines
and set some goals. Following are three basic, but very important
goals:
-
The use of these guidelines should result in readable code and should encourage
adherence.
-
The resulting documentation should be easy to maintain.
-
This document should be a living document in that as we discover better
ways to do things, it gets reflected here.
In order to write great software, you have to write software greatly. Vague?
Well, the point is that before you can produce great code, you have to
have developed a process for writing great code. And that is what these
standards are intended to help with.
Some amount of standardization is especially important in a large development
organization writing component software. Everybody will be in everybody
else's code, and that code must be clear. It must be clear what the
code does, how it should be used, how it can be extended, etc. The
standards within this document have been written to balance the group need
for standardization with the individual's desires to code in the ways they
feel most efficient.
SCOPE AND APPLICATION OF THESE
STANDARDS
It is very important to note that this document is divided into two distinct
areas -- Rules and Guidelines. It is very important
to recognize the following....
-
Rules are those coding standards that are "necessary and
required" coding practices that have been agreed upon by members of
the Java Communicator team. Everyone is expected to follow these "rules".
OVERVIEW OF THE DEVELOPMENT DOCUMENTATION
General Coding Rules
Naming Conventions
Commenting Code
General Coding Guidelines
Source Code Style Guidelines
Naming Guidelines
Layout of Source (.java) Files
Documentation for Methods
and Functions
GENERAL CODING RULES
Rules are those coding standards that are "necessary and
required" coding practices that have been agreed upon by members of
the Java Communicator team. Everyone is expected to follow these "rules".
NAMING
CONVENTIONS
Package Names
-
Package names should be single lowercase words.
Class Names
-
Concrete classes should use natural descriptive names, begin with a capital,
and have mixed case: FooBarReader
Member Function Names
-
Method ("member function") names should begin with a lowercase letter with
each subsequent new word in uppercase, and subsequent letters in each word
in lower case.
-
Methods for debug-only implementation should begin with "debug".
-
Static methods should begin with a capital letter with each subsequent
new word in uppercase, and subsequent letters in each word in lower case.
-
example
public class MyClass
{
void doSomethingNeat(int aValue);
void debugDumpToScreen();
static void SomeClassMethod(int aValue);
};
COMPONENT FACTORY NAMES
A component factory is a public class that implements only static methods.
These static methods are "Factory functions" or "component constructors".
Factory class names should include the word "Factory". Factory method
names should start with the word "Make." For example,
-
public class WidgetFactory
-
{
-
static Button MakeButton(int aButtonType);
-
static ListBox MakeListBox();
-
};
Function Naming Patterns
-
Getters and setters should begin with "get" / "set" and return the appropriate
object type.
-
Boolean getters should use "is" or "can" as a prefix, such as "isUndoable()"
rather than "getUndoable()"
COMMENTING CODE
All interfaces and public classes should have JavaDoc comments. See
the JavaDoc
documentation available from JavaSoft.
GENERAL CODING GUIDELINES
Guidelines are "suggested" coding practices that have
been written to recognize the need for individuality AND for common coding
practices. The purpose of the guidelines is to provide a framework upon
which we can all create better code. However, the guidelines are
not meant to impede engineering efforts when these guidelines are found
to be in direct conflict with an individual's preference, so long as that
preference is implemented consistently and is well documented. Finally,
because we recognize that this opens the code upon to individual stylist
coding habits, it is important that these habits are well documented and
will then become the basis for all other updates within the affected files,
i.e. when in someone else's code do as they do.
JAVA GRAMMAR
Wherever appropriate, avoid code that embeds many operations in a single
line. For example, avoid: someObject.doThis(i++,
otherObject.someField.doThat(), x?y:z). This kind of
code is error prone, difficult to decipher, and hard to maintain.
PARENTHESES
Parentheses are recommended for Boolean expressions to ensure proper
evaluation .
if (((someValue<foo(theParm)) &&
anotherValue) || todayIsMyBirthday)
TIP: Place constants on the left side of
your expressions; assignment, boolean and otherwise. This technique can
catch assignment (versus equality) errors, as well as promote constant
factoring for poor quality compilers.
CONSTANTS
Constants will use mixed case and begin with lowercase k. They offer
compile time type checking.
example
-
static final float kPi = 3.14159;
-
static final int kDaysInWeek = 7;
"MAGIC" NUMBERS
Literal ordinal constants embedded within source should almost never
be used. Whenever possible, use constants instead of literal ordinal constants:
example
-
int totalDays = 10 * DAYSINWEEK;
//boo, hiss!
-
static final int kDaysInWeek = 7;
//hooray! hooray!
DEBUGGING
-
First and foremost, understand how to write solid code. Then go back and
reread the java
programming language reference documentation from JavaSoft to refresh
you memory on the precedence order of operators.
-
Make sure every path of execution through your code has been thoroughly
tested. You can never do enough coverage testing. Here's a neat idea: try
actually stepping through each line! While you're hard at work testing
your code, be sure to throw invalid inputs at every public interface you
provide. The last thing we want to do is crash because your routine
didn't handle invalid inputs from ours. Never ever check
in code that doesn't compile.
-
Want to know the secret to fast code? Calculate those comparison values
once: reuse them often. Avoid global variables too, since they can wreak
havoc with the pre-fetch instruction queue.
-
It is our policy to produce code that can test itself to the greatest
extent possible. To that end, we encourage the use of three debugging techniques:
asserts, pre/post conditions and self testing methods.
1. Asserts
It is highly recommended that assert methods (warnings/errors) be used
to aid in debugging, especially to verify assumptions made in code. This
will be the technique used for reporting run-time errors and warnings.
2. Pre and Post Conditions
In order to bulletproof your code, you should use asserts to test all boundary
conditions. You're not doing any favors for anyone by "defensive" programming
practices that allow clients of your code to make improper calls.
In other words, it is better to blow up in debug builds if you are given
bad data rather than trying to "fix" the data and hide bugs.
example
-
String copyString(String aOtherString)
-
{
-
Assert.PreCondition(NULL != aOtherStr, "Null string
given");
-
...
-
Assert.PostCondition(fSelfString.length() >=aOtherString.length(),
-
"lengths don't match after copy.");
-
}
We do not want debug code to be included into release builds. Therefore,
all assertions are removed by the compiler (the java equivalent of #defines)
by flipping the debug flag in the Assert class.
3. SelfTest Methods
Each package will include a SelfTest class. This class should have
routines to thoroughly unit test every class in the package. If appropriate,
the SelfTest class may also contain methods for test integration between
the classes in this package, and between the classes in this package and
their dependencies in other packages.
Here is the rule for using SelfTest Methods: When you design your
class, you should design its unit test. When you design your package,
you should design your integration test. You are NOT done with the
implementation of a class until its unit test is implemented and can be
run successfully. You are NOT done with your package implementation
until all unit tests are coded and run successfully, and the integration
tests (if appropriate) are coded and run successfully.
SOURCE CODE STYLE
GUIDELINES
LINE SPACING
-
Line width should not ordinarily exceed 80 characters. Use your best judgment.
-
Tab sizes should be set equal to 2 spaces and set to be expanded to spaces.
BRACES
-
The starting brace can be optionally at the end of the conditional or on
the next line aligned with the conditional. The ending brace must be on
a separate line and aligned with the conditional. It is strongly recommended
that all conditional constructs define a block of code for single lines
of code.
-
We give some options below to accommodate the vast majority of programmer's
styles. HOWEVER, be consistent! When you pick
a style, stick to it. When editing another person's code, respect
the code, copy the style. (When in Rome, do as the Romans do).
IF / ELSE
Place the IF keyword and conditional expression on the same line.
examples:
if (expression)
{
statement;
}
else
{
statement;
}
or
if (expression) {
statement;
} else {
statement;
}
WHILE
The WHILE construct uses the same layout format as the IF construct.
The WHILE keyword should appear on its own line, immediately followed by
the conditional expression. The statement block is placed on the next line.
The curly braces may optionally be indented by up to 1 tab character. (1
TAB=2 spaces).
examples:
while (expression)
{
statement;
}
or
while (expression) {
statement;
}
DO..WHILE
The DO..WHILE form of the while construct should appear as shown below:
do {
statement;
} while (expression);
or
do
{
statement;
} while (expression);
SWITCH
The SWITCH construct uses the same layout format as the if construct.
The SWITCH keyword should appear on its own line, immediately followed
by its test expression. The statement block is placed on the next line.
The curly braces may optionally be indented by up to 1 tab character.
examples:
-
switch (expression)
-
{
-
case n:
-
statement;
-
break;
-
case x:
-
statement;
-
// Continue to default case
-
default:
//always add the default case
-
statement;
-
break;
-
}
-
or
-
switch (expression) {
-
case n:
-
statement;
-
break;
-
case x:
-
statement;
-
// Continue to default case
-
default:
//always add the default case
-
statement;
-
break;
-
}
TRY/CATCH/FINALLY
The try/catch construct is similar to the others. TRY keyword
should appear on its own line; followed by the open brace (optionally on
the same line); followed by the statement body; followed by the close brace
on its own line. Any number of CATCH phrases are next consisting
of the CATCH keyword and the exception expression on its own line; followed
by the CATCH body; followed by the close brace on its own line. The
FINALLY clause is the same as a CATCH.
examples:
-
try
-
{
-
statement;
-
}
-
catch (ExceptionClass e)
-
{
-
statement;
-
}
-
finally
-
{
-
statement;
-
}
-
or
-
try {
-
statement;
-
}
-
catch (ExceptionClass e) {
-
statement;
-
}
-
finally {
-
statement;
-
}
NAMING GUIDELINES
GENERAL
All type declarations should follow standard java package naming.
-
Package : All projects need to pick a prefix. The project
may split itself into any number of packages below this prefix. All package
names are entirely lower case. Remember, java tools are case sensitive,
and as of this writing somewhat inconsistent across platforms concerning
package names.
-
Interface : Everyone is encouraged to use the prefix "I"
in your interface classes, such as IPart. This is optional, but
strongly encouraged.
-
Constants : begin with const: constMyConstant
-
Global Types : begin with global: globalDays
(or "globalDays" is ok.)
-
File Names : match the class name in that file
MEMBER DATA NAMES
All member data will begin with a lowercase m, and then follow
the normal naming convention for other identifiers (mixed case, each word
beginning with uppercase). Keep in mind that providing publicly visible
member data reflects negatively on your family. Use access functions instead.
Respect the Java Beans coding patterns for member access unless you have
a good reason not to.
example
public class CxMyClass {
public void setMyOrdinalValue(int aValue);
public int getMyOrdinalValue();
private int mMyOrdinalValue;
};
PARAMETER NAMES
Parameter names should be constructed like identifiers, and include
the type in the name if the type is not explicit. They begin with lowercase
letters, and they typically start with the letter "a". Some
may feel "an" is more readable for parameters that start with a
vowel, such as "anObject."
example
public boolean numberIsEven(int aValue, Object anObject)
{
...
}
LAYOUT OF SOURCE FILES
(*.java)
The layout for a class will be broken up into the following main sections:
Copyright Notice, File Description; Package Name,
Imports, Constants, Methods, protected and private members. Each section
will be prefaced by an appropriate header block defining the section.
COPYRIGHT NOTICE
-
This will be the standard "legalese" copyright notice.
-
/************************************************************************
DISCLAIMER This material was prepared as an account of work sponsored by
an agency of the United States Government. Neither the United States Government
nor the United States Department of Energy, nor Battelle, nor any of their
employees, makes any warranty, express or implied, or assumes any legal
liability or responsibility for the accuracy, completeness, or usefulness
of any information, apparatus, product, software or process disclosed,
or represents that its use would not infringe privately owned rights.
-
ACKNOWLEDGMENT This software and its documentation were
produced with Government support under Contract Number DE-AC06-76RLO-1830
awarded by the United States Department of Energy. The Government retains
a paid-up non-exclusive, irrevocable worldwide license to reproduce, prepare
derivative works, perform publicly and display publicly by or for the Government,
including the right to distribute to other Government contractors. **************************************************************************/
-
FILE DESCRIPTION
-
This is a brief description of what the file is, does and represents. It
should describe the overview of how to use the file (or classes therein).
JavaDoc compatible commenting style is required. See the JavaDoc
documentation available from JavaSoft.
/* Description
* Appropriate Description.
* Description
*/
Also include the continuus headers. This
will be generated automatically if you create the file from continuus.
Or you can copy the header info from another file - don't forget to change
the author name to your own.
PACKAGE NAME
-
Package names should occur on the first non-commented line of the source
file and should following the naming conventions
defined in this document.
IMPORTS
-
Immediately following the package name should be the imported class names.
CONSTANTS
-
See the naming conventions defined in
this document.
METHOD DECLARATIONS
-
Each method is preceded by a description in JavaDoc format. Public methods
MUST have a standard javadoc comment header. These must be
professionally commented. Remember, you never know what code
will eventually be made public outside of here.
Standard access methods may be grouped without a description (access
methods assign or return an object attribute). Optionally, methods may
be grouped within logical groupings. Here are some suggestions...
-
Factory
-
Private
-
Protected
-
Interfaces
-
Accessor
-
Temporal (fickle)
-
I/O
-
Debugging
example
/* ======================================================= *
CONSTRUCTOR/DESTRUCTOR METHODS
* ======================================================= */
public CkSomeClass();
public CkSomeClass(CkSomeClass aSourceToCopy);
/* ======================================================= *
FACTORY METHODS (usually static)
* ======================================================= */
/** brief description */
public CkSomeClass createSomeClass(void){ }
/* ======================================================= *
ACCESSOR METHODS
* ======================================================= */
public int getState(void);
public void setState(int aNewValue);
/* ======================================================= *
STANDARD METHODS
* ======================================================= */
//...whatever these might be...
/* ======================================================= *
DEBUGGING METHODS
* ======================================================= */
void DoUnitTest(void);
-
CLASS DEFINITIONS
-
This section is the actual implementation of the class. Each method (and
private function) will be prefaced by the standard documentation header.
Read the Documentation
for Methods and Functions defined in this document.
DOCUMENTATION FOR METHODS AND
FUNCTIONS
The following standard has been established for the documentation of methods
and functions. Optional items are to be included only where applicable.
A complete description of each section in the routine documentation follows.
The header is designed to be easy to use. Many items are optional, and
may be omitted where they are not applicable. Each line item begins with
an asterisk, and ends with blank space. You do not place an asterisk next
to each line in a multiline component, only the topmost, next to the title.
All subsequent lines in multiline component are to be indented so that
they line up vertically with the previous line.
example
/**
* <Detailed description of method.>
*
* @param
<Description of each parameter>
* @return <explain
each return type>
* @exception <explain each exception>
* @author <your
name> <04-22-97 3:57pm>
**/
DESCRIPTION
Provide a detailed description. This may include:
-
intent of method
-
pre and post conditions
-
side effects
-
dependencies
-
implementation notes
-
who should be calling this method
-
whether the method should or should not be overridden
-
where to invoke super when overriding
-
control flow or state dependencies that need to exist before calling this
method.
PARMS SECTION
Describes the type, class, or protocol of all the method or routine
arguments. Should describe the parameters intended use (in, out,
in/out) and constraints.
example
-
* @param aSource - the input source string.
Cannot be 0-length.
RETURNS SECTION
This section is used to describe the method/routine return type. Specifically,
it needs to detail the actual data type returned, the range of possible
return values, and where applicable, error information returned by the
method. Also note that if the return value is self, you do not have to
specify a type (defaults to ID). All other cases require an explicit return
type specification.
example
-
* @return Possible values are 1..n.
EXCEPTION SECTION
The purpose section is a complete description of all the non-system
exceptions that this method throws. A description about whether the
exception is recoverable or not should be included. If applicable,
a recovery strategy for the exception can be described here. Remember,
when you throw a recoverable exception, you MUST reset the class state
for re-entrancy!
* @exception ResourceNotFoundException. recoverable, try another resource