Coding standards

Introduction

The coding standards for the Endefr project were written with a focus on simplicity and a preference for consistency over terseness.

Code in the project should be written for humans and not for compilers. Clarity is much more important than an unlikely performance gain. Modern compilers and runtimes have advanced code analysis tools which will generate very good code in most cases. Code will only be made less straightforward when measurements with a profiler have identified that spot as the bottleneck.

Not all rules are described in this document because it would become too long. But it should give a general idea about what is expected, so you can make an educated guess of what to do in situations which are not described here.

Encoding

All text files in the CVS must be stored in the ISO-8859-1 encoding. Use the support for this in your IDE to make it easy to adher to this rule.

File header

All Java source files must have the file header which can be found in templates/java-source-file-header.txt.

If you create or modify a file ensure the copyright statement is correct. Add your full name to the copyright statement. Also update the list of years if necessary. Do not include years in which the file was not changed, e.g. if a file changed in 2003 and in 2005 but not in 2004, the copyright statement should read 2003, 2005 instead of 2003-2005.

Documentation

Javadoc

Everything must have a Javadoc tag, even elements with low visibility (package private or private). Documentation is not only for users of Endefr, but also for its future maintainers.

The following Javadoc tags are required, i.e. they must be used when applicable. They are grouped per element type. See the Javadoc documentation (for Windows or Solaris) for an explanation of the tags:

@since

The tag @since only has to be used for public types, and public and protected members.

If you add new classes, constructors, methods or attributes to the project, you have to add tag @since which must have the value of the project version (defined in version.properties as project.version) without alpha, beta, development or distribution labels. For example: 1.01.00, 1.01.01, 2.05.13.

@deprecated

The tag @deprecated only has to be used for public types, and public and protected members.

In addtion to this tag the annotation @Deprecated has to be used.

@inheritDoc

{@inheritDoc} should only be used for methods within the same project. If {@inheritDoc} is used for elements overriding third-party libraries, the original documentation cannot be found.

Well-formedness

The Javadoc comments must be written so it easy to generate XHTML/XML documents, i.e. a doclet should not have to parse the comments to transform it to valid XML, but must be able to simply copy the text as is. Here is an example:

/**
 * <p>
 * Lorem ipsum &amp; foo bar.
 * </p>
 *
 * <hr />
 *
 * <p>
 * This file is part of the <a href="http://endefr.sourceforge.net/">Endefr
 * project</a>.
 * </p>
 * ...

Comments

Conditional blocks

For conditional statements, it is desirable to add a comment to the associated blocks which explains what the state at the beginning of the block is. The example shows that the comments add additional information beyond the information conveyed by the expression of the statement:

if (aItems.contains(pItem))
  {
  // STATE: the item has been processed before
  ...
  }
else
  {
  // STATE: the item has not been procssed before
  ...
  }

Empty blocks

All empty blocks must be documented. This ensures that other developers and development environments can differentiate between unfinished blocks and finished blocks. Besides stating that nothing should be done, explain what the consequences are. Here are some examples:

// No action needed, use default result of null.
// No action needed, retry on next run.
// No action needed, use default look and feel.

Naming

The naming scheme of the Endefr project prevents collisions with other user-defined identifiers and keywords by creating lots of separate namespaces through the use of prefixes. Currently only method names can collide with keywords.

Capitalization types

The following capitalization types will be used:

Element types

Here are the naming rules for each element type:

Packages
Types that will be distributed have to be in package net.sf.endefr or a descendant thereof. Types for tests, tools, etc. have to be in a descendant package of endefr. The names of subpackages are formatted using the all lowercase type: thisisapackage.
Types
Types are formatted using the full camel case type: ThisIsAType.
Methods
Methods are formatted using the standard camel case type: thisIsAMethod.
Constants
Constants are formatted using the all uppercase type: THIS_IS_A_CONSTANT.
Static attributes
Static attributes are formatted using the prefixed camel case type and and s as the prefix: sThisIsAStaticAttribute.
Attributes
Attributes are formatted using the prefixed camel case type and and a as the prefix: sThisIsAnAttribute.
Parameters
Parameters are formatted using the prefixed camel case type and and p as the prefix: sThisIsAParameter.
Local variables
Local variables are formatted using the prefixed camel case type and and l as the prefix: lThisIsALocalVariable.
Method result
The local variable that holds the result to be returned is named result.
Exceptions variables
Local variables holding caught exceptions are formatted using the prefixed camel case type and e as the prefix: eThisIsACaughtException.

Here is an example showing all element types:

package endefr.docexample;

public class CharWriter
  {
  public static final String DEFAULT_ENCODING = "ISO-8859-1";

  public boolean attemptToWrite(String pFilename, char pCharacter)
    {
    boolean result = false;

    try
      {
      FileOutputStream lFileOutputStream;

      lFileOutputStream = new FileOutputStream(pFilename, true);
      try
        {
        OutputStreamWriter lWriter;
        String lEncoding;

        lEncoding = aEncoding == null ? DEFAULT_ENCODING : aEncoding;

        lWriter = new OutputStreamWriter(lFileOuputStream, lEncoding);
        try
          {
          lWriter.write(pCharacter);
          result = true;
          }
        finally
          {
          lWriter.close();
          }
        }
      finally
        {
        lFileOuputStream.close();
        }
      }
    catch (IOException eIO)
      {
      // No action needed, attempt failed.
      }

    return result;
    }

  private static CharWriter sInstance;

  private String aEncoding;
  }

Boolean types

Boolean attributes, variables and methods returning booleans, should be written as a question. Other verbs than be can be used, e.g. canEat(...), lShouldDrawBorder, isEmpty() and contains(...).

Abbrevations

Abbrevations (including acronyms) should be written capitalized, e.g. HTML becomes Html.

Miscellaneous

Runtime requirements

Do not depend on specific runtime environments to provide functionality, e.g. special class loaders, AOP and EJB. It must be possible to instantiate and use a class in a simple program.

Types

Put each type in its own file no matter how small the type is.

Do not use inner classes except for very simple anonymous inner classes.

Ensure each class has at least one constructor even if the constructor is equal to the default constructor. This allows the user to set a breakpoint in the constructor, which is not possible with the default constructor.

Each class implementing Serializable must have a serial version UID to make sure that when the class is changed without affecting the serialized format, previously serialized objects can still be read.

Members

Members should be ordered in the following order. First by visibility:

Then sort by member type:

This order is only a guide. Use your own judgement when you feel the order above will make the code less clear and/or when the initialization order requires a different declaration order.

The reasoning behind the ordering above is that sombody reading the source for the first time will probably be interested in how the public API is implemented. As he wants to know more details he has to go further down in the file.

Methods

Use a single exit point. If a method returns a result, put the result in a variable called result.

Statements

Always use blocks for statements which can either have a single statement or a block as its child.

Put local variable declarations at top of blocks, and initialize them after the declarations. This makes the first statement which assigns to the variable look the same as following statements, and makes it easier to move assignment statements around.

Never use labels, the break and continue statements. The break statement is allowed to be used in switch statement because otherwise it would make the switch statement useless.

Expressions

Only use assignment operators in assignment statements and never in expressions.

Do not use the increment (++) and decrement (--) operators. These operators have side effects and provide no advantage beyond terseness. Use the addition (+=) and subtraction (-=) assignment operators.

this variable

Avoid the use of this to qualify method invocations, attribute access, etc. The naming rules ensure distinction between local variables, attributes, etc., making use of this to access members unnecessary.

Modifiers

Don't use public, static and final for members of interfaces. These modifiers are the same for all members, so explicitly stating them is redundant.

Only use final if required, e.g. enabling access from anonymous inner classes or constants, or when enforcing correctness is important, e.g. object ID attributes. Do not use final as a compiler optimization hint. It won't help much if anything at all because compilers and runtimes optimize very well without hints. You also make it more cumbersome to change the code when needed in the future.

Other rules

Besides the rules above, lots of code checks have been enabled in the Eclipse project. If you encounter a situation not described above or checked by Eclipse, prefer simplicity, clarity and flexiblity over other concerns when making a decision.

Static code checkers

There are a number of static code checkers available. The Endefr team wants to add one or more to the future build system.

Formatting

The formatting rules are described in the Eclipse settings which are provided in the CVS. There are too many settings to repeat them here.

You will notice that the formatting rules use lots of vertical space. We feel the extra vertical whitespace improves legibility a lot. Working with the source files should not be a problem with large screens and powerful navigation capabilities of IDEs available nowadays.


The project page of Endefr at SourceForge.net