Gwydion Style Guide for Java

The Gwydion Group has developed a set of guidelines for programming in Java. Since we have it, we figured we might as well share it with the rest of the world. Except for what's mentioned in the Hypercode Style section, this style guide has nothing to do with Sheets.

We generally follow the "standard" Java style, as exemplified by Sun's books and the code distributed with the JDK. Our major departures are documentation comments and order of declarations.

Note on terminology: Most things in this guide are mandatory -- if you don't follow them, you're in violation of the style guide. (Whether you care is up to you) However, on some issues there is no real consensus. In that case, there is usually a recommended style, and an acceptable style. The recommended style is the style recommended to people with no real opinions on the issue, while the acceptable style allows dissidents to fall within the bounds of good style.

General

An indent level is two spaces. All code must be formatted for an 80 character wide display.

Open curly braces belong on the same line as the thing which opened them:

    if (foo) {
      bar();
    }

rather than

    if (foo)
    {
      bar();
    }

An exception to this rule is made for function headers; see section on definitions for details.

Naming Conventions

Identifiers should follow the Java mixedCase convention. Classes and constructors should begin with uppercase letters, and fields and methods should begin with lower case letters. The only exception is for constants (static final fields), which are all uppercase and use underbars to separate words. Examples:

    class NormalClass {
      int normalField;
      static final int CONSTANT_FIELD;
    } 

Subclasses will often be named by taking the superclass and adding an adjective to the front of it. For instance, one subclass of Dialog is named FileDialog.

Method names are usually verb phrases (preferred), like updatePreview, or properties of the class (less preferred), like allTokens. Methods that return booleans should begin with is, as in isString. Methods that act as simple wrappers for fields should be named getField and setField, respectively.

Usually, methods that take an index into a collection should use the word At in the name, as in setElementAt. Similarly, methods that find elements in a collection should generally end in the word Of, as in indexOf. (The Java Beans style guide suggests an alternate convention for the first form, omitting the word At. The Java language alternates between including At and omitting it.)

Definitions

In Java, definitions are class headers, methods, fields, and constructors. (They are sometimes referred to as top level forms, but this is not really accurate because they can be nested) The word function is used to mean method or constructor.

Definitions should be separated by a blank line (and not by a blank comment line).

For all definitions, it is suggested that access control modifiers (public, protected, and private) go first, then synchronized or transient, then static or abstract, then final.

The Gwydion Group does not follow the Java convention of ordering class members by access control. The Java convention is to declare public members first, then protected members, then package, then private, and within each level put fields before methods. We prefer to organize our code by concept, not access control.

For definitions with bodies, the curly braces may go in any of three places:

    header { body }

    header {
      body
    }

    header
    {
      body
    }

It should be emphasized that this is the only time an open curly brace may go on a blank line.

Long class headers may be broken before an extends or implements clause. The new lines should be indented two indent levels.

Field definitions may be broken before the = sign, just like a local variable declaration (see next section). The new line should be indented a single indent level.

Function headers should have a space between the function name and the parameter list. Long function headers may be broken in either of two places:

In the first case, the new lines should be indented two indent levels (four spaces). In the second case, the lines should be indented just inside the open paren of the parameter parenthesis (that is, one column beyond the column of the open paren).

Examples:

    // Style 1
    static boolean shadows (JavaFunctionComponent specific, 
                            JavaFunctionComponent general)

    // Style 2
    static boolean shadows
        (JavaFunctionComponent specific, JavaFunctionComponent general)

If the function contains a throws clause, the header may be broken directly before it, indenting the new line two levels.

Functions should not be too long. What constitutes "too long" is obviously a judgment call, and will vary by circumstance as well as by author. Nick's guideline is that functions should fit in one screenful (roughly 35 lines).

Statements

Statements with braces should have the opening curly brace on the same line as the beginning of the statement. If the statement has intermediate keywords (like the else in an if statement), it is recommended that the intermediate keyword share a line with a close curly brace, if possible.

It is acceptable but by no means required to use braces when they are not syntactically required.

There should always be a space following any comma or semicolon, and any colon used as part of a label (both break labels and case labels). Curly braces and statement keywords (if, for, switch, etc.) must always be surrounded by whitespace.

There are two preferred ways to format an if statement, and two acceptable but not recommended ways:

    // one liner format
    if (foo) { bar(); } else { baz(); }
 
    // multi-line format
    if (foo) {
      bar();
    } else {
      baz();
    }
 
    // "William style" multi-line if -- not recommended
    if (foo) {
      bar();
    } 
    else {
      baz();
    }
 
    // condensed multi-line format -- not recommended
    if (foo) { bar(); }
    else { baz(); }

Obviously, braces and else clauses can be omitted.

In an else if construct, the else and the following if should go on the same line:

    if (foo) {
      bar();
    } else if (quux) {
      baz();
    }

try statements should be indented like if statements:

    try {
      body();
    } catch (Error e) {
      handleIt();
    } finally {
      doSomething();
    }

case clauses inside switch statements may be formatted in any of three ways:

    case LABEL: foo(); break;
 
    case LABEL:
      foo(); break;
 
    case LABEL:
      foo();
      break;

It is recommended that the formatting between case clauses in the same switch statement be kept fairly consistent. If it is inconvenient to use the same style for all clauses, consider putting the shorter clauses at the top and the longer clauses at the bottom of the switch statement.

If the break part of a switch statement is intentionally omitted, there should be a large comment saying so.

for statements should be formatted in the obvious way:

    for (int i = 0; i < 10; i++) {
      whatever();
    }

If the iteration uses non-standard numeric loop bounds (like i=1; i<=10), there should be a comment explaining why. If the header is long, the line may be broken after a semicolon.

Labels (those used with break, not case labels) should go on their own line and be indented one level less than the code they label. Example:

      someCode();
    bigLoop:
      for (int i = 0; i < 10; i++) {
        if (something)
          break bigLoop;
      }
      postLoop();

A variable declaration may be wrapped before the = sign:

    String type 
      = exprType(balanceRBracket(index - 1) - 1, context);

Expressions

The Java unary operators are:

    ! ~ ++ --

There should be no space between a unary operator and its operand. (Exception: Occasionally it is useful to put a space between a ! and a heavily parenthesized expression) Unary expressions should not be split across lines.

The Java binary operators are:

    + - * / % ^ & && | || << >> >>>
    += -= *= /= %= ^= &= |= = <<= >>= >>>=
    == != <= < > >=

Generally, there should be a space around any binary operator. However, this whitespace is sometimes omitted to emphasize operator precedence, as in:

    if (foo+1 < 10)

Binary expressions may be wrapped before an operator and indented with one extra indent level from the open parenthesis. Example:

    if (token.kind == JavaParserConstants.BOOLEAN
          || token.kind == JavaParserConstants.CHAR
          || token.kind == JavaParserConstants.BYTE)

The ternary operator in Java is the ?: operator. The three standard styles are:

    (condition) ? x : y
 
    (condition) ? x
                : y
 
    (condition)
      ? x // indented one indent level
      : y

Note that in all three cases, the condition is wrapped in parenthesis, even though it is not syntactically necessary. Nesting the ternary operator should be done sparingly.

For array access, there should be no spaces between the array and the open bracket.

For function calls, there should be a space after every comma, and no space between the function name and the argument list. The call may be broken directly after a comma:

    g.drawString(view.dispLines[line2].substring(0, ind2 + 2), 0,
                 base + line2 * view.lineHeight());

In extreme cases, the function call may also be broken immediately before the opening paren of the argument list:

    methodWithAReallyLongName
      (view.dispLines[line2].substring(0, ind2 + 2), 0,
       base + line2 * view.lineHeight());

Also in extreme cases, an expression may be broken before a dot ("."):

    something.somethingElse.somethingElseStill.gettingLongerByTheMinute
      .drawString(foo, bar);

However, both of these forms should be reserved for emergencies, as they really are quite ugly.

Comments

The // line comment is the mainstay of commenting. It belongs before the code being commented and should be indented to the same level. There should be a single space between the // and the text of the comment. There should be no blank lines or blank comment lines between the comment and the code. Example:

    // Comment
    int foo;

Comments that contain multiple paragraphs should be connected by a blank comment line, i.e., a line consisting of nothing but //. Example:

    // Paragraph 1
    //
    // Paragraph 2
    int foo;

A comment attached to a top-level definition is known as a header comment. Header comments are meant to describe the definition to casual observers; comments about gory implementation details should go inside the function's body. (This is a gray area. While "gory" details should be left out, not so gory details like bugs, performance estimates, and overviews of implementation are sometimes included.)

A free-standing comment is one that does not describe any one piece of code. There must be a blank line between a free-standing comment and any nearby code.

Same line comments may be used to document code inside of a function:

    int localVariable = 3; // This is a same line comment

There should be at least one space between the code and the comment. Same line comments should not be used on definitions, because Sheets does not handle them well.

/* */ comments should be used sparingly, and only for commenting out code -- never for documentation purposes. /** */ comments (Java documentation comments) should never be used -- they are ugly and duplicate the functionality of header comments.

The issue of what needs to be commented is a difficult one. In general, every class, method, field, and constructor needs a comment which describes what it does. There are two situations in which a definition does not need a comment: When there is a group comment that describes several definition together, and when the comment would merely repeat the obvious. (The latter is obviously quite subjective. A good example of an "obvious" comment is what you'd write after implementing an abstract method like SheetComponent.export() -- "Does what an export() method ought to do.")

It is recommended that a definition's name not be repeated at the top of its comment -- readers can just glance down and see it, so repeating the name is a waste of typing and space.

Miscellaneous

Aside from indentation, code should not be aligned into columns, because it is too hard to maintain. For example, the following is bad:

    // Wrong
    int someVar       = someValue;
    int longerVarName = someOtherValue;
    int x             = 3;

Array types should always have the brackets next to the base type (without any spaces in between), and never after the variable or method.

    // Right
    int[] foo;
 
    // Wrong
    int foo[];

Hypercode Style

To the most part, Sheets is agnostic about style. There are a few places, however, where following the Gwydion style guide will make Sheets work better.

First, the class name abbreviation that Sheets does in the table of contents panel depends upon the naming conventions for classes. If you don't follow those conventions, Sheets will generate stupid abbreviations.

Also, Sheets distinguishes between header comments and free-standing comments by observing whether there are any blank lines between the end of the comment and the first non-comment. Similarly, Sheets uses blank lines to tell the difference between a multi-paragraph comment and several independent comments. See section on comments for details.

Sheets has two features that are real handy for organizing code: Separator components and named comments. A separator component appears as a horizontal line. They are heavy weight separators; they are generally put between classes, and no where else.

The other feature is the named comment. If a free-standing comment has a colon in the first line, anything before the colon is considered its name. The name is used in the table of contents panel to the left of the main panel. Named comments are used mainly as lightweight separators, although occasionally a large free-standing comment deserves a name. Named comments are frequently used to divide a large class into sections.

 


[Go back to index]

Copyright (c) 1997 Carnegie Mellon University. All rights reserved.