Titanomachia Server Components

Coding Standards

 

Introduction

This document outlines a set of coding standards for the Java Programming Language. These standards should be adhered to and enforced on this project. The primary purpose of these coding standards is to enforce the following constraints:

  • consistency - all source code on this project should be consistent in readability.
  • safety - many of the coding standards cover safe coding practices found to be best of breed.
  • maintainability - if all of the code in the project has a similar look and feel, then newcomers to the project should not have too much difficulty in jumping right in since they know what to expect.

Coding standards compliance is non-negotiable. The standards, however, are highly negotiable. If there is a dispute, desire to change, or necessity to add to these standards, then a proposal should be made to the entire team and the team as a whole will vote for the proposed change(s). These standards are a first pass at a living document of coding standards for this project.

For the most part these standards should work well within many different editors and development environments. Many of the code formatting standards come from the automatic code formatting found within the Emacs text editor. It is recognized that certain IDEs (Integrated Development Environments) may not be capable of supporting these standards, or its successors (most notable VisualAge for Java). This is the fault of the IDE, not the standards :P therefore the user of the IDE will be required to enforce these coding standards within the IDE, switch IDEs, or move to a text editor that can support the standards.

 


Standards for Readability and Consistency

White Space

All white space within source code will be composed of spaces (the wide key at the bottom of the keyboard). Tabs (or especially the dreaded combination of spaces and tabs intermixed) are to not be used. If your IDE or editor cannot perform this simple task, then do not use it on this project!

The basis for this standard comes from development environments and text editors interpreting the tab character differently. This can cause some pretty interesting results when the source code is opened in another environment (especially vi when attempting to correct a production issue). Another area this standard covers is printing. When printing you will occasionally get a different tab expansion, and using spaces resolves this issue as well.

80 Column Maximum

All source code will conform to an 80 column maximum width. This allows the printing of source code to be legible and provides the potential for copying/pasting inside of word processors with a minimum of fuss. Furthermore, when used in conjunction with the previous standard, allows source code editting in production-like environments with the dreaded vi text editor.

Import Statements

Import statements will be granular to the class, not the package (i.e. it is not valid to import java.io.*). Furthermore, all imports for a given package will be grouped together and alphabetized by class name. Please refer to SampleCode.java for further details. Impact analysis can then be automated or determined via a quick visual inspection and cyclic dependencies (c.v) are easy to find. When a particular class is no longer necessary, then it should be removed from the import section of the source code.

Class Documentation

Regardless of importance, scope, or use all classes will be documented with JavaDoc comments, with no exceptions. Included in the JavaDoc will be the original and modifying authors with HTML hyperlinks to e-mail addresses and version comments for all class versions. It is of paramount importance to stringently document all interface declarations with class documentation as well.

This is incredibly important!

Class Declaration

The scope, modifier, class name, and super class will appear on one line. If the class implements any interfaces, then the interface portion of the declaration will appear on a separate line.

Basic Class Declaration

public class MyClass {
}

Class with Super Class Declaration

public class MyClass extends Observer {
}

Class with Interfaces

public class MyClass
  implements Runnable {
}

Combining it all Together

public class MyClass extends Observer 
  implements Runnable, Serializable {
}

At first glance, this standard may seem ridiculous. The point of this standard is to separate the portion of the declaration that states what an object is and what an object can be treated as on two different source code lines.

Interface Declaration

The scope, modifiers, and interface name will be declared on the first line of the interface declaration, any interfaces being extended will appear on the second line similar to class interface implementation.

Basic Interface

public interface MyInterface {
}

Interface with Extensions

public interface MyInterface
  extends Remote, Serializable {
}

Class Layout

All classes will be layed out in a 6 + n sectional pattern. All classes will contain the following six sections, in the order shown (even if those sections are empty):

  1. constants (denoted by the usage of the keyword final)
  2. properties (this includes static properties).
  3. construction (including static and instance initializers).
  4. operations
  5. accessors
  6. mutators

Accessors and mutators will be in the same order as the properties.

In addition to the mandatory six sections the following sections will be created as applicable:

  • Super Class Overrides: for each super class that methods are being overidden from, there will exist a section for those overrides. This ensures that the programmer does not need to go traipsing through source code to determine where the code belongs, makes it easy to remove overrides when inheritance is removed, and makes it very easy to find.
  • Interface Implementations: for interfaces (other than marker interfaces) that are implemented by a class, there will exist one section per interface implemented.
  • Main: if the class implements a main() method, then a separate section will exist for this method. This section must be the last section in the class.

All sections will be separated by the following documentation to increase visibility of sectional breaks:

  /////////////////////////////////////////////////////////////////////////////
  // section name

But What About Interfaces

The following sections are required for interfaces:

  1. constants
  2. operations
  3. accessors
  4. mutators

Constant and Property Documentation

All constants and object proeprties will have JavaDoc comments that provide a clue as to the usage and purpose of the variable. There will also be a custom JavaDoc tag - @since that should indicate the class version that first introduced the variable.

Constant and Property Declaration

All properties will be declared private. No exceptions. All access to member variables will be via accessors and mutators. No Exceptions.

Constants will be declared final static and will be initialized either via static initializer or inline. Constants do not require accessors or mutators. Constants are not required to be public.

Method Documentation

All methods, regardless of usage, are required to have JavaDoc comments. There are no exceptions. The following rules apply to JavaDoc comments:

Overridden Methods and Interface Implementation

All that is required is a description of this implementation and an @see construct back to the original method declaration.

Newly Created Methods

Must document what the method does, or method intent for abstract methods, parameters, return values, and all exceptions raised.

Method Declaration

Please review the following samples.

No Exceptions, fits in 80 Characters

  public Entity doSomethingInteresting(int entityID) {
  }

No Exceptions, Does Not Fit in 80 Characters

  public void doSomethingInteresting(int entityID, Entity sibling, 
                                     InputStream dataSource) {
  }

Exceptions, Fits in 80 Characters

  public Entity doSomethingInteresting(int entityID) 
    throws IOException, InterestingException {
  }

Exceptions, Does Not Fit in 80 Characters

  public void doSomethingInteresting(int entityID, Entity sibling, 
                                     InputStream dataSource) 
    throws IOException, InterestingException {
  }

 


Standards for Safety

No Cyclic Dependencies

Nowhere in the project's source code should there exist a situation where two classes are directly dependent upon one another (cyclicly dependent). Resolve these conflicts with interfaces. The rationale is to create independently testable objects. Refer to Lakos' book Large Scale C++ Software Design for a full treatise on this subject.

Test Drivers

If it is important enough to be a class, then it is important enough to be tested. Therefore a test harness will be created for each class. This project will use JUnit for test harness creation. Please note the following:

  • Test harnesesses do not need to be created for interfaces.
  • It is valid to create inner-class implementations of abstract classes in order to create a test harness.
  • Test harness class names should be {class-name}Test

Curly Braces...

...will surround the body of all if, else, else if, and other compound statements -- even if there is only one line of code.

Case/Switch Statements

Are to be avoided (aka not allowed) within the production source code of this project. In lieu of this construct, utilize an interface abstracted Strategy Pattern and a hashtable of instances. This approach leverages the object-oriented power of the Java programming language and ensures that an object's source code will not be littered with duplicate, yet poorly maintainable code.

Avoid Use of Fully Qualified Class Names

Use an import statement. This way tools can be used to determine impact of changing or removing a class. Note: This may not always be possible or useful -- note the SampleCode class and its use of fully qualified class names -- this is deemed an appropriate usage. Obviously there are going to be times when usage is required.

Avoid Inner Classes

99% of the time the usage of an inner class denotes a certain level of laziness or apathy (I know, I've created many), the remaining 1% of the time may actually include a real componentization (or physical model packaging) constraint that should be followed. If an inner-class, especially an anonymous inner class, has a piece of functionality that can be re-used external to the component that owns the declaration, then the inner class usage is invalid.

Sample

The following is a sample of how all Java source code will look on this project.

package com.sample;

import java.io.File;
import java.io.IOException;

import java.rmi.Remote;
import java.rmi.RemoteException;

import java.util.Iterator;
import java.util.List;

/**
 * <p>The intent of this class is to provide a sample, or foundation layer, for
 * the coding standards to be used on this project. This class is not intended 
 * to be production level source code, but mearly an example of what 
 * production level source code should look like.</p>
 *
 * <p>As the coding standards evolve this source code should change so there 
 * exists a reference implementation.</p>
 *
 * @author <a href="mailto:bes@theinternet.com">bes</a>
 * @author <a href="mailto:fadams@algoresinternet.com">fadams</a>
 *
 * @version 1.0 - bes - initial class creation. primarily responsible for 
 *                creating this object's thread of execution.
 * @version 1.1 - fadams - added object naming and unique ID number.
 * @version 1.2 - bes - added instance initializer.
 */
public class SampleCode extends Object
  implements Remote, Runnable {

  /////////////////////////////////////////////////////////////////////////////
  // CONSTANTS

  /**
   * The unique ID of this object.
   *
   * @since 1.1
   */
  public static final String UID = "1234567890A";

  /////////////////////////////////////////////////////////////////////////////
  // PROPERTIES

  /**
   * Collection of instantiated SampleCode objects for cleanup purposes.
   *
   * @since 1.0
   */
  private static List cleanup;

  /**
   * The name of this object.
   *
   * @since 1.1
   */
  private String name = "default";

  /**
   * The owning thread for this object.
   *
   * @since 1.0
   */
  private Thread owner;

  /////////////////////////////////////////////////////////////////////////////
  // CONSTRUCTION

  /**
   * Static initializer. Invoked first time class is loaded. Creates the 
   * collection of objects that require cleanup.
   *
   * @since 1.1
   */
  static {
    cleanup = new java.util.ArrayList();
  }

  /**
   * Instance initializer. Invoked prior to all constructors.
   *
   * @since 1.2
   */
  {
    cleanup.addObject(this);
  }

  /**
   * Default constructor.
   *
   * @since 1.0
   */
  public SampleCode() {
  }

  /////////////////////////////////////////////////////////////////////////////
  // OPERATIONS

  /////////////////////////////////////////////////////////////////////////////
  // ACCESSORS

  /**
   * Retrieve the name of this object.
   *
   * @return The objects name.
   * @since 1.1
   */
  public String getName() {
    return name;
  }

  /**
   * Accessor/factory method for the owning thread.
   *
   * @return The thread that owns this object.
   * @since 1.0
   */
  public Thread getOwner() {
    if (null == owner) {
      owner = new Thread(getName());
    }

    return owner;
  }

  /////////////////////////////////////////////////////////////////////////////
  // MUTATORS

  /**
   * Store a new name for this object.
   *
   * @param aName The new name
   * @since 1.1
   */
  public synchronized void setName(String aName) {
    name = aName;
  }

  /**
   * Set the thread that owns this object.
   *
   * @param aThread The owning thread.
   * @since 1.1
   */
  public void setOwner(Thread aThread) {
    owner = aThread;
  }

  /////////////////////////////////////////////////////////////////////////////
  // OVERRIDES -- java.lang.Object

  /**
   * Calculate this objects hash code value.
   *
   * @return The hash code value of this object.
   * @see java.lang.Object#hashCode
   * @since 1.1
   */
  public int hashCode() {
    return getName().hashCode();
  }

  /////////////////////////////////////////////////////////////////////////////
  // INTERFACE - java.lang.Runnable

  /**
   * Code executed within this objects "thread of execution"
   *
   * @see java.lang.Runnable#run
   * @since 1.0
   */
  public void run() {
  }
}

Any problems, misinformation, corrections, comments, flames, etc. should be directed to this site's administrator.