Translations of this page:

ZipTie Coding Standard

This document uses the following terms to define enforcement:

  • MUST - this convention is a requirement
  • require - same as MUST
  • should - this convention is a strong suggestion
  • prefer - same as should

Where possible these standards will be enforced by Checkstyle.


Braces

Curly braces MUST appear on a line by themselves, and align with the keyword with which they are associated.

Incorrect:

   {
       if (something) {
          variable = 0;
       }
   }

or

   {
       if (something)
          {
             variable = 0;
          }
   }

Correct:

   {
       if (something)
       {
          variable = 0;
       }
   }

Blocks

We do not allow implicit blocks, this is due to subtle errors that can be introduced.

Incorrect:

   {
      if (something)
         variable = 0;
   }

Correct:

   {
      if (something)
      {
         variable = 0;
      }
   }

Whitespace

We require whitespace between blocks (implicit or explicit).

Incorrect:

{
   if (!something)
   {
      return false;
   }
   try
   {
       doSomething();
   }
   catch (Exception e)
   {
       log.error("Something bad happened.");
   }
   return true;
}

Correct:

{
   if (!something)
   {
      return false;
   }
 
   try
   {
       doSomething();
   }
   catch (Exception e)
   {
       log.error("Something bad happened.");
   }
 
   return true;
}

Note this does not mean a blank line after the last statement in an enclosing scope.


Declarations

When declaring members that are collections, you should use the most generic form of the collection:

public class Foo
{
    private Set<State> stateMap;
 
    public Foo()
    {
        stateMap = new HashSet<State>();
    }
}

As seen in the example above, we prefer the delaration to be absent the allocation.

NOT PREFERRED:

public class Foo
{
    private Set<State> stateSet = new HashSet<State>();
    ...
}

The same is true of static members if they are non-primative types or require method invocations to initialize:

public class Foo
{
    private static final int BUFFER_SIZE = 1024;     // this is OK
 
    private static final boolean IS_UNIX;
    private static final Set<State> stateSet;
 
    // Statics initialized here
    static
    {
       stateSet = new HashSet<State>();
       IS_UNIX = (getOs().indexOf("nix") > 0 ? true : false);
    }
}

NOTE: it is acceptable to use a single-line declaration/initializer in the case of a Log4j logger:

   private static final Logger DEV_LOG = Logger.getLogger(Foo.class);

Collections

The use of Vector, Hashtable are forbidden. These are internally synchronized collections with a locking granularity that is inappropriate for use within a server. Similarly, Stack (a subclass of Vector) is also forbidden, instead use a LinkedList (using the addLast() and removeLast() methods).

Know your collection classes! Java5 adds a new package java.util.concurrent. Spend an hour and literally read all of the JavaDoc for these classes, they are designed for use in products like servers. In particular, in a multi-threadeded context there is no reason to use and synchronize on a HashMap instance; instead, use ConcurrentHashMap. This is an extremely high-performance thread-safe Map implementation that is synchronization-free in all but a few cases.

Lastly, you MUST use the interface associated with a collection when declaring members, parameters. Preferred is the use of the generic interface for local variables. For example, even if the implementation of a collection is ArrayList, declare the variable to be of type List. Similarly so with Map, Set, and Queue. The only exception is if you can demonstrate that knowledge of the collection type is critical to understanding the code or accessing methods only available on the specific collection class.


JavaDoc

All classes, and methods (regardless of scope), MUST include JavaDoc. JavaDoc comments for methods MUST include @param and @return markup if applicable. Member variables are optional.

The hard line-length limit on comments is 160 characters, however, try to keep JavaDoc comment lines below 120.

For JavaDoc styles, please refer to http://java.sun.com/j2se/javadoc/writingdoccomments/#styleguide


Overloading equals()

If you overload the equals() method, you MUST overload the hashCode() method.

Additionally, we prefer the following pattern for equals:

   public boolean equals(Object obj)
   {
      if (obj == null)
      {
          return false;
      }
      else if (this == obj)
      {
          return true;
      }
 
      try
      {
          Foo f = (Foo) obj;
          return this.value == f.value;
      }
      catch (ClassCastException cce)
      {
          return false;
      }
   }

This pattern has shown to be extremely performant in the nominal case in which a 'Foo' object is passed into the above method. It avoids explicit checks for class equivalency and in the 'failure' case performs as well as 'instanceof' based implementations on most JVMs.

'Covariant' equals() implementations are strongly discouraged. A covariant equals() method is an equals method declared to take an object of a specific type (rather than Object). Covariant equals have been shown to introduce subtle bugs. The 'pain' of casting, as above, is fairly light.


Code Organization

Code MUST appear in the following order in a class:

Members

Members MUST appear in this order:

  • public statics
  • protected statics
  • package statics
  • private statics
  • <blank line>
  • public members
  • protected members
  • package members
  • private members

Static Blocks

An anonymous static block runs when the class is loaded and can be used to initialize static members (including static final members!). It MUST appear after the members, but before the constructors.

Constructors

Constructors MUST appear in this order:

  • public constructors
  • protected constructors
  • package constructors
  • private constructors

Methods

In accordance with the Java Language specification, sections 8.1.1, 8.3.1, and 8.4.3 the preferred order for method modifiers is: public, protected, private, abstract, static, final, transient, volatile, synchronized, native, strictfp

Methods MUST appear in this order:

  • public methods (static and instance)
  • protected methods (static and instance)
  • package methods (static and instance)
  • private methods (static and instance)

There is no ordering currently imposed within a given scope block. So, for example, public methods need not be in alphabetical order.

Additionally required is a 'separation banner' between each, for example:

   // ------------------------------------------------------------------------------
   //                      P U B L I C    M E T H O D S
   // ------------------------------------------------------------------------------

Enums

Java5 enums are in reality a class, and implicitly extend java.lang.Enum just as classes extend java.lang.Class. Public enums should be defined in a separate file. Private enums should appear in the inner class section mentioned below.

Preferred is this format:

   private enum State
   {
       PARSING,
       GENERATING,
       COMPILING,
       COMPLETE
   }

Rather than this format:

   private enum State {PARSING, GENERATING, COMPILING, COMPLETE}

Enums can do all kinds of CrAZy things in Java5 – they can implement interfaces, extend other enums, contain methods, implement value-specific class bodies (!), and can be generic.

Currently, we discourage ALL of these possibilities with these exceptions:

  • An enum may implement Serializable, and contain a SerialVersionUID
  • An enum may implement toString() in such as way as to provide meaningful string representations
  • An enum may override any of the methods in java.lang.Enum. These include, but are not limited to: equals(), hashCode(), name(), and ordinal().

Any use of the other capabilities will have to be lobbied for heavily in a code review.

Inner Classes

Inner classes must appear in the following order:

  • protected inner classes
  • private inner classes

Currently, public and package scoped inner classes would have to be lobbied for in a code review, but generally speaking they are not allowed.

Inner classes that exceed 200 lines should be considered for a package-scoped first-order class, even if it is only utilized by the containing class.

Inner classes that access no containing class members should be considered for a package-scoped first-order class.

Static inner class? What are you smoking? Lobby for it in a code review.

Required is a 'separation banner' above the first inner class, for example:

   // ------------------------------------------------------------------------------
   //                         I N N E R   C L A S S E S
   // ------------------------------------------------------------------------------

Example

This example class employs most of the above semantics (it does not contain JavaDoc for brevity):

public class Demonstration
{
   // -- Statics
   public static final String EXTERNAL_CONSTANT = "External Constant";  
   protected static final Map STATE_MAP;
   private static final int BUFFER_SIZE = 1024;
 
   // -- Members
   protected BlockingQueue queue;
   private State currentState;
   private int maxValue;
 
   // -- Static initializer
   static
   {
      if (Boolean.getProperty("ThreadSafe"))
      {
         STATE_MAP = new ConcurrentHashMap();
      }
      else
      {
         STATE_MAP = new HashMap();
      }
   }
 
 
   // ----------------------------------------------------------------
   //                    C O N S T R U C T O R S
   // ----------------------------------------------------------------
 
   public Demonstration(int size)
   {
      queue = new LinkedBlockingQueue(size);
      currentState = State.INITIAL;
   }
 
   private Demonstration()
   {
      // there is no public default constructor.
   }
 
   // ----------------------------------------------------------------
   //                   P U B L I C   M E T H O D S
   // ----------------------------------------------------------------
 
   public static int getMapSize()
   {
      return STATE_MAP.size();
   }
 
   public int getMaxValue()
   {
      return maxValue;
   }
 
   public void setMaxValue(int value)
   {
      maxValue = value;
   }
 
 
   // ----------------------------------------------------------------
   //                 P R O T E C T E D   M E T H O D S
   // ----------------------------------------------------------------
 
   protected void enqueue(Object obj)
   {
      queue.offer(obj);
   }
 
   protected State getCurrentState()
   {
      return currentState;
   }
 
 
   // ----------------------------------------------------------------
   //                   P R I V A T E   M E T H O D S
   // ----------------------------------------------------------------
 
   private void resetState()
   {
      currentState = State.INITIAL;
   }
 
 
   // ----------------------------------------------------------------
   //                   I N N E R   C L A S S E S
   // ----------------------------------------------------------------
 
   protected enum State
   {
      INITIAL,
      PARSING,
      BUILDING, 
      COMPLETE,
   }
 
   private class Parser implements Runnable
   {
      public void run()
      {
         // run method
      }
   }
}
 
dev/coding_standard.txt · Last modified: 2008/01/12 08:22 by brettw
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki