CroftSoft / Library / Tutorials

CroftSoft Java Style Guide

David Wallace Croft

2012 Mar 03 Sat


Table of Contents

Introduction

This is the CroftSoft guide for styling source code in the Java programming language. Within each category, the guidelines are prioritized by how confident I am that they are required to ensure that Java source code is readable and maintainable. Guidelines toward the end of a category are less important than those toward the beginning.

White Space

In general, the CroftSoft style makes liberal use of white space which decreases code density and improves readability. Overall, code listings in this style tend to be tall and thin.

Indent using spaces instead of tabs

The width of a tab character varies depending on the editor settings used to view the code. This can make cleanly formatted source code look unreadable when viewed by someone other than the original author.

To insert space characters instead of tab characters in the Eclipse Integrated Development Environment (IDE) for Java and Ant files:

  • Window / Preferences / General / Editors / Text Editors / Insert spaces for tabs

  • Window / Preferences / Ant / Editor / Formatter / Use tab character instead of spaces: unchecked

  • Window / Preferences / Java / Code Style / Formatter / Edit... / Indentation / General settings / Tab policy: Spaces Only

Set the right margin to 76

At one time, code had to be 80 columns wide maximum. This no longer applies but limiting width to 80 characters or less makes it easier to read in an IDE and in print. At least one book publisher requires that code listings be limited to 76 columns.

To show and set the print margin in the Eclipse IDE:

  • Window / Preferences / General / Editors / Text Editors / Show print margin

  • Window / Preferences / General / Editors / Text Editors / Print margin column: 76

  • Window / Preferences / Ant / Editor / Formatter / Line Wrapping / Maximum line width (characters): 76

Set the left margin to 4

Use the margin on the left for remarking out blocks of code and high priority TODO comments so that they immediately stand out. Assuming an 80 character page width, a left margin of 4 matches the right margin width of 4 when the print margin is set to 76.

Example:


    public int  calculate ( )
    ////////////////////////////////////////////////////////////////////////
    {
      final int  a = b + c;

// TODO:  This code needs to be reviewed.

//      return a / e;

      return b / e;
    }

In the Eclipse IDE, there is no option to display a left margin line.

Indent 2 spaces

Java is a heavily indented programming language and the CroftSoft Java style only uses 72 characters per line, i.e., 80 characters minus margins on each side of 4 characters. Indenting just 2 spaces allows for near maximum indentation levels and always aligns indented code on even-numbered columns. Indenting less at just one space would be error-prone.

Example:


    public void  printXyz ( )
    ////////////////////////////////////////////////////////////////////////
    {
      for ( int  x = 0; x < xCount; x++ )
      {
        for ( int  y = 0; y < yCount; y++ )
        {
          for ( int  z = 0; z < zCount; z++ )
          {
            System.out.println ( "x = " + x + ", y = " + y + ", z = " + z );
          }
        }
      }
    }

To indent two spaces in the Eclipse IDE:

  • Window / Preferences / General / Editors / Text Editors / Displayed tab width: 2

  • Window / Preferences / Ant / Editor / Formatter / Indentation / Tab size: 2

  • Window / Preferences / Java / Code Style / Formatter / Edit... / Indentation / General settings / Indentation size: 2

  • Window / Preferences / Java / Code Style / Formatter / Edit... / Indentation / General settings / Tab size: 2

Braces

Align opening and closing braces vertically

This is known as the Allman style. It is the most readable of the brace indentation styles as it minimizes confusion as to which closing brace goes with which opening brace.

Example:


    public void  printXyz ( )
    ////////////////////////////////////////////////////////////////////////
    {
      for ( int  x = 0; x < xCount; x++ )
      {
        for ( int  y = 0; y < yCount; y++ )
        {
          for ( int  z = 0; z < zCount; z++ )
          {
            System.out.println ( "x = " + x + ", y = " + y + ", z = " + z );
          }
        }
      }
    }

To use the Allman style in the Eclipse IDE:

  • Window / Preferences / Java / Code Style / Formatter / Edit... / Braces / Brace positions / [all]: Next line

Always use braces with an if or for statement

Although using braces to mark off a single line of code as a block is optional, doing so improves readability.

Example:


      // without braces

      if ( found ) System.out.println ( "Success" );

      for ( int  i = 0; i < size; i++ ) System.out.println ( i );

      // without braces

      if ( found )
        System.out.println ( "Success" );

      for ( int  i = 0; i < size; i++ )
        System.out.println ( i );

      // with braces

      if ( found )
      {
        System.out.println ( "Success" );
      }

      for ( int  i = 0; i < size; i++ )
      {
        System.out.println ( i );
      }

Modifiers

I recommend that future programming languages default to private and final. The intention to make classes, methods, variables, and arguments non-private or non-final should require an explicit modifier to prevent unintended exposure.

Use private wherever possible

Generally you want to make everything private. Only give as much access to your class methods and variables as is required. For future changes to source code, you can always make a private method public but you cannot go the other way around without risking breaking a dependency.

If it cannot be private, mark it as public instead of protected or default package-private. Once you have provided access to a variable to a subclass or a class in the same package, you might as well provide access to all classes.


    package com.croftsoft.lab.example01;

    public final class  HelloWorld
    ////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////
    {

    private static final String
      DEFAULT_NAME = "World",
      TEXT_PREFIX  = "Hello, ",
      TEXT_SUFFIX  = "!";

    //

    private final String  name;

    [...]

    ////////////////////////////////////////////////////////////////////////
    // private methods
    ////////////////////////////////////////////////////////////////////////

    private static String  formatName (
      final String     defaultName,
      final String...  names )
    ////////////////////////////////////////////////////////////////////////
    {
      [...]
    }

    ////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////
    }

Use final wherever possible

Marking your variables and method variables as final can prevent mistakes where values are unintentionally assigned.

With regard to marking classes as final, keep in mind that you can always change your source code from final to non-final but you cannot go the other way around without risking breaking a dependency.

If your class is marked final, it is not necessary to mark your methods as final as they cannot be overridden. It does not hurt to do so, however.


    package com.croftsoft.lab.example01;

    public final class  HelloWorld
    ////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////
    {

    private static final String
      DEFAULT_NAME = "World",
      TEXT_PREFIX  = "Hello, ",
      TEXT_SUFFIX  = "!";

    //

    private final String  name;

    ////////////////////////////////////////////////////////////////////////
    // public static methods
    ////////////////////////////////////////////////////////////////////////

    public static void  main ( final String [ ]  args )
    ////////////////////////////////////////////////////////////////////////
    {
      final String  helloText = new HelloWorld ( args ).sayHello ( );

      System.out.println ( helloText );
    }

    ////////////////////////////////////////////////////////////////////////
    // constructor methods
    ////////////////////////////////////////////////////////////////////////

    public  HelloWorld ( final String...  names )
    ////////////////////////////////////////////////////////////////////////
    {
      this.name = formatName ( DEFAULT_NAME, names );
    }

    ////////////////////////////////////////////////////////////////////////
    // public methods
    ////////////////////////////////////////////////////////////////////////

    public String  sayHello ( )
    ////////////////////////////////////////////////////////////////////////
    {
      return TEXT_PREFIX + name + TEXT_SUFFIX;
    }

    ////////////////////////////////////////////////////////////////////////
    // private methods
    ////////////////////////////////////////////////////////////////////////

    private static String  formatName (
      final String     defaultName,
      final String...  names )
    ////////////////////////////////////////////////////////////////////////
    {
      if ( names == null )
      {
        return defaultName;
      }

      final StringBuilder  stringBuilder = new StringBuilder ( );

      boolean  isFirst = true;

      for ( final String  name : names )
      {
        if ( name == null )
        {
          continue;
        }

        final String  trimmedName = name.trim ( );

        if ( trimmedName.equals ( "" ) )
        {
          continue;
        }

        if ( isFirst )
        {
          isFirst = false;
        }
        else
        {
          stringBuilder.append ( " " );
        }

        stringBuilder.append ( trimmedName );
      }

      final String  formattedName = stringBuilder.toString ( );

      return formattedName.equals ( "" ) ? defaultName : formattedName;
    }

    ////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////
    }

Javadoc

Javadoc can be useful but if it merely provides redundant information already available in a descriptive variable name or method signature, it is best left out to prevent cluttering the source code.

Append your author tag for even minor changes

The javadoc author tag assists with code maintenance by indicating which developers have worked on a particular file previously. This can be very important in tracking down knowledge within an organization. Everyone who modifies a source code file should append their author tag following the previous author tags using their full name.

If you change even just a single byte of whitespace in a Java source code file, you should add your author tag. To do otherwise is to attribute to the author or authors already listed work that they did not do, good or bad. If you do not want to add your author tag, you should at least list an author tag name of "unattributed" to indicate that the authors listed are not solely responsible for the current version of the file.

If you are modifying source code and no previous developers have added their author tags, list "unattributed" as the name for the first author tag above your own.


    package com.croftsoft.lab.example01;

    /***********************************************************************
    * Example class for the CroftSoft Java Style Guide.
    *
    * @version
    *   $Date$
    *   $Rev$
    *   $Author$
    * @since
    *   2011-11-30
    * @author
    *   David Wallace Croft
    * @author
    *   Second Author Name
    * @author
    *   Third Author Name
    * @author
    *   unattributed
    ***********************************************************************/
    public final class  HelloWorld
    ////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////
    {

Use the svn:keywords property

The source code version control system Subversion provides the ability to automatically update the source code file with the timestamp, revision, and developer identifier when source code is committed. This can be extremely useful during debugging in identifying at a glance whether the file has been modified recently and who did so. Other source code version control systems such as CVS provide similar functionality.

To enable svn:keywords in the Eclipse IDE using the Subclipse plugin:

  • Right-click on the base source code directory

  • Team / Set Property...

  • Property name: svn:keywords

  • Enter a text property: Author Date Id Rev

  • Set property recursively: checked

  • Insert the dollar-sign delimited tokens $Author$, $Date$, $Id$, and $Rev$ into your source code. The tokens will be expanded automatically the next time you commit.

You can use the keywords to automatically update your javadoc version tag. The Id tag can sometimes run past the right print margin border for files with long filenames so I prefer to use Date, Rev (revision), and Author, each on a separate line.


    package com.croftsoft.lab.example01;

    /***********************************************************************
    * Example class for the CroftSoft Java Style Guide.
    *
    * @version
    *   $Date: 2011-11-30 20:06:58 -0600 (Wed, 30 Nov 2011) $
    *   $Rev: 198 $
    *   $Author: croft $
    * @since
    *   2011-11-30
    * @author
    *   David Wallace Croft
    ***********************************************************************/
    public final class  HelloWorld
    ////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////
    {
 
 
 
CroftSoft
 
 
About
Library
-Books
-Code
-Courses
-Links
-Media
-Software
-Tutorials
People
Portfolio
Update
 
 
Google
CroftSoft Web

 

Creative Commons License
© 2011 CroftSoft Inc.
You may copy this webpage under the terms of the
Creative Commons Attribution License.