r2 - 07 Jun 2007 - 22:26:14 - BrettWooldridgeYou are here: TWiki >  Developer Web  > CodingStandard

Main.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 Map<State> stateMap;

    public Foo()
    {
        stateMap = new HashMap<State>();
    }
}

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

NOT PREFERRED:

public class Foo
{
    private Map<State> stateMap = new HashMap<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 Map<State> stateMap;

    // Statics initialized here
    static
    {
       stateMap = new HashMap<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. In fact, given the introduction of the Lock interface and it's implementers there is no reason to ever use the synchronized keyword.

Lastly, you MUST use the interface associated with a collection when declaring members, parameters, and 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
         }
      }
   }

-- BrettWooldridge - 30 Jan 2007

Edit | WYSIWYG | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r2 < r1 | More topic actions
Developer.CodingStandard moved from Main.CodingStandard on 07 Jun 2007 - 22:26 by BrettWooldridge - put it back
 
Powered by TWiki
This site is powered by the TWiki collaboration platformCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback