Project

General

Profile

Coding Conventions

This chapter documents the code conventions followed in the development of the Java source code in the FWD Project. These conventions have been developed to maintain a consistent standard of quality across the project, in order to improve its readability and ease its maintenance. Contributors are asked to adhere to these conventions in any patches, updates, or new code submitted for inclusion in the project. Source code which violates these conventions will not be checked into the project.

We understand coding style is largely a matter of personal taste, and that no set of code conventions will satisfy all people all of the time. For some, opinion and discussion about code conventions can border on the philosophical and religious. Even the core FWD developers had to compromise on numerous points to reach consensus on the final version of conventions you see here! Nevertheless, we ask that you respect our decisions - which we will do our best to explain - as you sit down in front of your editor and begin hacking away.

There are numerous aspects of code conventions, and where we had no strong feelings, we decided not to re-invent the wheel, but rather to build upon the foundations other thoughtful engineers had long since constructed. To that end, you are encouraged to review the following documents:

This chapter documents those topics for which we either felt further clarification was necessary, or with which we flat-out disagree. As such, please consider the topics explicitly discussed here to have the highest precedence; these conventions should be followed where a conflict exists with either of the publications listed above. Where this document is silent on an issue, please follow The Elements of Java Style. Where that book is silent on an issue, please follow the Java Code Conventions document.

Some of the conventions are identified as rules, while others are noted as guidelines. As the name suggests, a rule is a practice that is required for code to be included in the FWD project. Guidelines are somewhat softer, generally because they require some judgment which is difficult to codify into a rule. These are recommendations we encourage FWD developers and contributors to follow.

Rules and guidelines are organized into the following categories:

  • Code Structure: organization of Java classes among and within source files.
  • Code Format: details of indents, spacing, block format, method signatures, etc.
  • Symbol/File Names: naming conventions for variables, methods, classes, files, etc.
  • Documentation: comments and intra-source file documentation.
  • Best Practices: approaches to follow for clearer/better code.

Finally, we realize that not all of the FWD source code (particularly that contained in the oldest or in experimental modules) conforms with all of the conventions outlined here, nor does some of the Java code produced by the FWD conversion technology. Shame on us, but this simply was not the highest priority in making the technology work in its first generation. Nevertheless, the proportion of FWD project source code which complies is quite high, and we are striving for complete coverage as the technology continues to be developed.

As for Java code generated by the conversion process, a near term (but not necessarily high priority) goal is to produce converted output which complies with those conventions for which it is practical and feasible to do so (generally those which define structure and format). The longer term goal is to make the code conventions followed by the conversion process configurable, since we believe the owner of the original code should have a say in the style of the converted code. It is not as realistic, however, to expect to comply with some of the softer guidelines and approaches, since the state of the converted code in this respect largely will be predetermined by the code conventions employed by the authors of the original, Progress 4GL code.

Code Structure Conventions

Java Class File Organization

Type: Rule

All Java class/interface files must be ordered in the following manner:

  1. FWD source code standard file header
  2. package statement
  3. import statements
  4. class definition
  5. all enum declarations
    1. public
    2. protected
    3. package private
    4. private
  6. all data members
    1. public static
    2. protected static
    3. package private static
    4. private static
    5. public instance
    6. protected instance
    7. package private instance
    8. private instance
  7. all methods
    1. static initializers
    2. constructors
    3. public static (except main)
    4. protected static
    5. package private static
    6. private static
    7. public instance
    8. protected instance
    9. package private instance
    10. private instance
    11. main
  8. inner classes

Note that many of the above items are optional within a Java class, but if present, they should be in the order specified. Although the optional main method of a class has both the public and static modifiers, it is not grouped with other public static methods in the class. It is placed at the bottom of the class for easy identification.

Top Level Classes

Type: Rule

There should never be more than one top level class in a single source file. Each top level class belongs in its own .java file.

Inner Classes

Type: Rule

Inner classes should be created thoughtfully. Generally they are useful to:

  • create a helper class whose structure or interface is never used outside of the containing class;
  • create a specialized implementation of a public interface or abstract class for external code to use (e.g., an AWT or Swing listener or a custom Iterator).

If you find yourself trying to figure out how to construct an instance of inner class Foo.Bar from outside of the Foo class, rethink your design. You should never have to write the following code:

   Foo.Bar myBar = new Foo.Bar(a, b, c);

Code Format Conventions

TAB Character

Type: Rule

The hard tab character (a.k.a., Horizontal Tab, ASCII character 0x09, '\t') should be eliminated from all source code. The main reason is that the number of spaces the tab represents is not defined by any standard. So some editors may show it as 3 spaces, others as 5, or whatever. Subsequently, the number of characters of indentation cannot be guaranteed, therefore attempts to nicely format your code when displayed in one editor, may result in horribly unreadable code in another.

In addition, access from command line tools may yield unpredictable results when encountering tabs. Since there is no reason to use tabs instead of spaces, always use spaces.

See also:

  • Indention

Carriage Return Character

Type: Rule

The carriage return character (a.k.a. ASCII character 0x0D, '\r') should be eliminated from all source code. The main reason is that this character is handled (as a line end delimiter) differently on different systems by some software (such as e-mail clients, version control systems, etc.), leading to apparent corruption of files.

Indention

Type: Rule

Indentions are always to be made using 3 spaces (no hard tabs!). So, the first level of indentation would start in the first column. The 2nd level would start 3 characters indented (in column 4), and so on:

123456789012345678901234567890123456789012345678901234567890

public class MyClass          // ← indent level 1 (column 1)
{
   /** Some variable */       // ← indent level 2 (column 4)
   private int someVar = 0;

   /**
    * Constructor.
    */
   public MyClass()
   {
      doSomething();          // ← indent level 3 (column 7)
   }

   ...

This consistency improves readability and is in line with a wide range of common practice. However, note that this is different from many Sun Java examples, which may use 4 characters or 2 characters.

The first line of any method must be indented 3 spaces from the column of the opening curly brace. In other words, do not treat the first indention differently from any other indention. Every open curly brace indents 3 and every close curly brace indents -3.

The only code that is not indented by at least 3 spaces is the following:

  • file header/change log
  • package statement
  • import statements
  • class JavaDoc
  • first line of class definition
  • opening and closing curly braces for the class

See also:

  • TAB Character

Using Blank Lines for Spacing

Type: Rule

i) For inline source code comments which document one or more lines of conceptually related source code, do not put a blank line between the comment and the lines to which it refers (its subject). For example, this is desirable:

// Tell my object to do some things.
myObject.doSomething();
myObject.doAnotherThing();

...and this is undesirable:

// Tell my object to do some things.

myObject.doSomething();
myObject.doAnotherThing();

ii) For inline source code comments which document multiple groups of lines of conceptually related source code, do use a blank line as a spacer between the comment and the first line of source code, to make it easier for a reader to understand that the comment is associated with more than just the first group of lines. For instance:

// Write remaining output, then flush and close the stream.

out.write("hello");
out.write("world");

out.flush();

out.close();

Do not omit the blank line after the comment, which suggests the comment is only related to the immediately following two lines of code:

// Write remaining output, then flush and close the stream.
out.write("hello");
out.write("world");

out.flush();

out.close();

Note that the preceding rule applies only to inline comments, not to JavaDoc comments. For JavaDoc comments, no line should be placed between the comment and the class, method or member to which it refers.

iii) Do not place blank lines after an opening curly brace ({) or before a closing curly brace (}). Correct:

if (size > 0)
{
   size--;
}

Incorrect:

if (size > 0)
{

   size--;

}

iv) Data members, methods, and inner classes should all be separated by a blank line. For instance:

/**
 * Sample class.
 */
public class MyClass
{
   /** Sample instance variable 1 */
   private int counter = 0;

   /** Sample instance variable 2 */
   private boolean saved = false;

   /**
    * Sample constructor.
    */
   public MyClass()
   {
   }

   /**
    * Sample method.
    */
   public void increment()
   {
      counter++;
   }

   /**
    * Sample inner class.
    */
   private static class MyInnerClass
   {
      /** Data member */
      private int myVar = 10;
   }
}

v) Before the start of a block or after the end of a block, use a blank line, except in the case of nested blocks, where no blank lines should intervene. For example:

public myMethod(int size)
{
   for (int i = 0; i < size; i++)
   {
      if (i == someVariable)
      {
         if (someVariable == 1000)
         {
            System.out.println("Skipping special case!");

            continue;
         }

         matchedSomeVariable = true;
      }

      counter++;
   }
}

Line Length

Type: Guideline

Each line of code should be no longer than 78 characters. Code should be readable at any text terminal with any text viewer. A developer should make no assumption about who will read the code, where and under which conditions.

See also:

  • Breaking Long Method Declarations
  • Breaking Chained Method Calls
  • Breaking Long Method Calls
  • Breaking Long Expressions

Breaking Long Method Declarations

Type: Rule

In situations where a method signature is too long, break first by splitting each parameter onto a separate line and lining these up for readability. Always start the "throws" list on a separate line and then line up the exception names on separate lines, in the same column, for readability. Do not indent the throws statement. It should have the same indent level as the beginning of the method signature.

public synchronized static String logon(HttpServletRequest request,
                                        Customer customer,
                                        String password)
throws InvalidLogonException,
       ApplicationSecurityException,
       DatastoreException,
       Exception
{
   ...

If necessary, insert an addition split between the access specifiers and the return type. Try to avoid this if possible as it really reduces readability. Note that the 2nd line is not indented any further than the first line.

public synchronized static
LongReturnType logonToSystem(HttpServletRequest request,
                             Customer customer,
                             String password)
throws InvalidLogonException,
       ApplicationSecurityException,
       DatastoreException,
       Exception
{
   ...

See also:

  • Line Length

Breaking Chained Method Calls

Type: Rule

Method chaining is a useful device in the Java programmer's tool kit, but it can be abused at the price of code clarity. Use it sparingly, and if you must create long chains of method calls, break them across lines for readability:

   String someText = myObject.doSomething()
                             .doAnotherThing()
                             .doAThirdThing()
                             .toString();

Note that the dot (.) operator is carried to the next line for each new method invocation, and the operators are aligned in the same column.

See also:

  • Line Length

Breaking Long Method Calls

Type: Rule

Method calls longer than 78 characters should be wrapped such that the first line includes at least the first argument (if any), and subsequent lines contain additional arguments. Alternative implementations of this rule are acceptable. For instance, one approach is to place multiple arguments per line, as in:

   String someText = myObject.veryLongMethodName(arg1, arg2, arg3,
                                                 SOME_LONG_CONSTANT_NAME,
                                                 ANOTHER_LONG_CONSTANT_NAME);

...or to place each argument on its own line:

   String someText = myObject.veryLongMethodName(arg1,
                                                 arg2,
                                                 arg3,
                                                 SOME_LONG_CONSTANT_NAME,
                                                 ANOTHER_LONG_CONSTANT_NAME);

It is even acceptable to split a single argument across multiple lines, if it is a lengthy expression:

   String someText = myObject.veryLongMethodName(arg1, arg2,
                                                 BITFIELD_ONE   |
                                                 BITFIELD_TWO   |
                                                 BITFIELD_THREE |
                                                 BITFIELD_FOUR  |
                                                 BITFIELD_FIVE,
                                                 SOME_LONG_CONSTANT_NAME,
                                                 ANOTHER_LONG_CONSTANT_NAME);

However, a preferred approach would be to place the lengthy expression in a separate statement, store its result in a temporary variable, then pass that variable as an argument to the method call. We believe this improves readability:

   int arg3 = BITFIELD_ONE   |
              BITFIELD_TWO   |
              BITFIELD_THREE |
              BITFIELD_FOUR  |
              BITFIELD_FIVE;

   String someText = myObject.veryLongMethodName(arg1, arg2, arg3,
                                                 SOME_LONG_CONSTANT_NAME,
                                                 ANOTHER_LONG_CONSTANT_NAME);

See also:

  • Line Length

Breaking Long Expressions

Type: Rule

Generally follow rule №6 as documented in the The Elements of Java Style book, however note that when breaking complex expressions, the FWD convention is to leave (and align) the operators at the end of the line:

   if ((height == 86 && weight > 210) ||
       justify != misnomer            ||
       (finalBreak == 100 && breakGroup < 3))
   {
      ...
   }

There is no perfect solution to this kind of problem, but leaving the operator at the end of the line and aligning associated operators can make the expression more readable.

Long assignment line breaks are optimally made at the assignment operator if there is no method call that can be used to split the line.

private static final String PUBLIC_PATHS_KEYSTORE =
   "security.public-paths.key-store";

See also:

  • Line Length
  • Breaking Long Method Calls
  • Breaking Chained Method Calls

Symbol/File Name Conventions

Documentation Conventions

Best Practices


© 2004-2017 Golden Code Development Corporation. ALL RIGHTS RESERVED.