Java Coding Standards (DRAFT)

by the ACS Java Team.

Edited and maintained by Bryan Quinn.


The purpose of this document is to establish a set of standards for any code written in Java for use in the ArsDigita Community System. An illustrative example of a HelloWorld program is referenced throughout. This example is available for download.

Introduction

A good developer knows that there is more to development than programming. A great developer knows that there is more to development than development. (Ambler, 1999)
A recurring problem encountered by developers working on software projects is the maintenance of legacy code. When you first write a piece of code, its contract and implementation may be clear to you, but it is likely that it is not clear to anyone else. To solve this problem, professional programmers adhere to standards. The application of a standard ensures that the APIs and implementations of your program are clear to anyone familiar with the standard. This not only helps others use your code, but will assist you when you to understand what the code does at a later date.

Working in Java can increase this problem because it can be sometimes be easier to write code quickly in Java than in other compiled langauges like C. It is best to sit down, away from the computer, and think about the APIs and requirements for your code before implementing it.

File standards

One level of standards is in the code itself. Please:
  1. You should Observe a 78 column limit in all source code. Even though modern graphical editors are capable of fitting more than 78 columns onto one line, printing programs are often not senstive to this and many people prefer to use terminal editors which enforce 78 columns. One way to make this convenient is to change the size of your editing window to only allow for 78 columns display. Almost all editors will display the number of columns on a line to assist with this.

    If you're over 78 columns in one line, you may be editing a long String. In Java, you need to use the concatenation operator (+) to join together Strings on multiple lines:

    String myLongString = "This is a very long string that goes on" +
        "for a considerable amount of time before finally stopping\n.";
          

  2. All files should contain within them an \$Id\$ header for use by CVS. CVS will expand this header and identify the last time someone touched the file and print their CVS login name. All Java class files should have a final static String member called cvsId. The identifier can be accessed with the ident program to identify the version of a compiled class file.

  3. All files should include the standard ACS headers, documented later in this file.

Documentation

If your program isn't worth documenting, it probably isn't worth runnning. (Nagler, 1995).

In order for someone to use a piece of code that you have written, it must be carefully documented. You may feel that your class is not important enough to explain or that its use is self-evident from the code itself. If that is so, then it is highly questionable that your class provides a useful abstraction or that it is useful towards any end. When you write some code, it is because you are attempting to solve a problem, but your solution is not accessible unless there is some documentation to describe it.

Some people challenge this by saying that clear code requires no documentation. To some extent, this is true. Certainly, clear code requires less documentation than complex code. It is also preferrable to simplify complex code and then document it, rather than simply document the complexities. However, Nagler raises a real point in the quote that opens this section: no matter how clear a piece of code is, the comments describing it will be more instructive, particularly to someone trying to understand your code quickly.

Documentation goes above and beyond the level of code. You should always consider writing documentation and diagrams that explain the requirements, design, and use of any code that you right and include links to such material in the code itself.

Fortunately, Java provides its own self-documenting language for code, Javadoc. The documentation system for Tcl procedures in ACS 3.4.x and above included a Javadoc-like documentation facility that could be accessed through an API Documentation browser. ACS Java only provides the Javadoc generated documentation for procedures, accessible at the same URL, /api-doc. Unlike the Tcl version, Javadoc must be explicitly invoked in order for the documentation to be rebuilt.

Javadoc provides a number of directives to add documentation to classes and methods. All classes should contain a comment that explains:

/**
 * This is a simple HelloWorld program to illustrate the ACS
 * Engineering Standards.
 *
 * Adapted from Davis, M. (2000) "Incremental development with Ant and JUnit"
 * http://www-4.ibm.com/software/developer/library/j-ant/index.html
 *
 * @author Bryan Quinn
 * @version 1.2 2001/01/21 01:49:34
 * @since ACS 4.0
 */
For methods, at a minimum, whether it is public or private, should contain documentation that explains the contract or responsibilities of the function. This contract should contain:

In addition to the description of the contract, all parameters should be described with @param and the information being returned (if applicable) should be documented with @return.

    /**
     * A Java Application must contain a static main method which is executed
     * when the application starts.  This application simply prints
     * Hello World to the console.
     *
     * @param args a <code>String[]</code> value; this application ignores any arguments passed.
     */
    public static void main ( String [] args ) {
	HelloWorld helloWorld = new HelloWorld();
	System.out.println(helloWorld.sayHello());
    }

    /**
     * This method returns the string "Hello World".
     *
     * @return The string "Hello World"
     */
    public String sayHello() {
	return ("Hello World");
    }

See How to Write Doc Comments for Javadoc for full information on how to effectively use Javadoc.

Naming

"What's the use of their having names," the Gnat said, "if they won't answer to them?"
"No use to THEM," said Alice, "but it's useful to the people who name them, I suppose. If not, why do things have names at all?"
Lewis Caroll, Through the Looking Glass
The importance of names is often overlooked by programmers. However, from the perspective of reading and maintaining code, transparent variable names are crucial. The ability to simply skim a line of code and identify what is occurring depends on a clear name that describes what the function does.

A key benefit to descriptive naming is that it establishes a conceptual consistency to your work. For example, the Java 2 Core APIs follow consistent standards for the names of methods of functions. When one becomes familiar with one piece of the core APIs, the knowledge of the syntax of the APIs encoded in its naming transfers over to consideration of other APIs. This makes it much easier for developers to get up to speed on the Java APIs. The Java APIs were designed well, and many programs written in Java also strive to follow these conventions. We have the same goal for the ACS. If you strive to follow this example, you can produce code that other developers will adopt with ease and your code will be read and reused with ease. To be a successful open-source program, the code must meet this standard.

Class names should begin with a capital letter and contain a noun. The rest of the name should be lowercase, but because Java does not allow spaces, denote additional words with a capital letter, e.g. SqlFragment.

Method names should begin with a lowercase letter and obey the standard capitalization rule for additional words. Method names should be of the form verbObject, where the object is optional. For example, toString() and getValue().

Field names can be flexibly defined, but should be easy to understand. Stay over from overly short names, such as int i or vague names like selection. Field names should begin with a lowercase letter and obey the standard capitalization rule, e.g. acsForm and httpRequest. Other tips:

Packages

Java packages exist to establish a namespace for class names. I might have two classes named User, but one might be in the com.arsdigita.acs package, and the other might be in the java.security package. Because the classes are separated into packages, there is no conflict if the same program uses both of them.

Package Purpose
com.arsdigita.acs The central ACS classes.
com.arsdigita.acs.db The database API.
com.arsdigita.acs.* Any package that is part of the core, such as ACS Administration, should get its own Java package for its class files, for example, com.arsdigita.acs.acs-admin.
com.arsdigita.* Any package that is not part of the core, such as BBoard, should get its own package, for example com.arsdigita.bboard. However, if the package is not being maintained by ArsDigita, the com.arsdigita should be replaced by something more appropriate.

File Headers

Here are examples of file headers to use when writing code.
  1. Java and ACSJ files:
    package com.arsdigita.acs;
    
    /**
     * What the class does.
     *
     * @author <a href="mailto:bquinn@arsdigita.com">Bryan Quinn</a>
     * @version 1.2 2001/01/21 01:49:34
     * @since ACS 4.0
     */
    
    public class New { 
        public final static String cvsId = "java.html,v 1.2 2001/01/21 01:49:34 bquinn Exp";
    
    }
    
  2. AJP files Here is an example of a AJP file. Note that it includes identification of the author, creation date, and cvs-id.
    <%@ include file="/acs.jspi" %>
    
    <%
    
    ad_page_contract {
    
        Document the file's purpose here.
    
        @author Bryan Quinn (bquinn@arsdigita.com)
        @creation-date 10/10/2000
        @cvs-id java.html,v 1.2 2001/01/21 01:49:34 bquinn Exp
    
    } {
     
    } -properties {
    
     }
    
          // Insert code here.
    
    ad_return_template 
    %>
          
    

Working with Objects

Java forces programmers working in the language to work within an Object-Oriented framework. Instead of writing pure procedural code, as one does in PL/SQL and Tcl, all Java code must be written using classes. A class, simply defined, is a collection of fields and methods. Collectively, the components of a class are referred to as members. Fields are variable declarations that are themselves other classes or primitive datatypes, such as int and float. Methods are procedures (code that takes 0 or more arguments and has no return type) and functions (code that takes 0 or more arguments and has a return type).

Here is an example of a class. The document will refer to this example when describing reccomendations for working with classes.

class Foo {
    private int foo, bar;           2 private fields.
    private String baz;             Another private field, a String.

    public Foo () {                 A public constructor.
        foo = 4;
        bar = 5;
    }

    public String getBaz() {        A public accessor procedure. 
        return baz;
    }

    public void setBaz(String baz) {A public mutator function.
        this.baz = baz;
    }

    public int getNum(boolean b) {  A public accessor function with some logic.
        if (b == 1) {
            return foo;
        } else {
            return bar;
        }
    }
}

Testing

For testing, we use JUnit.

Keep a professional attitude

When you go against a standard, document it.
(Ambler, 1999)
The above comprise a set of guidelines that the ACS Java team has constructed to make our own work more efficient and useful. However, it can't possibly cover every case and there are always occasions when the guidelines above should be overriden. When doing so, please document why, so that readers of the code can understand why the change was necessary. However, the usual causes of broken standards is deadline pressure. One response to this is to maintain a professional attitude towards your work.

Programmers believe in the necessity for high standards of code and often cite deadline pressure and tight schedules as impediments to adopting it. The first response you can make when forced into such a situation is to explain a business case for the necessity for documentation and an adjustment of the schedule:

The key message is that software quality requires time, but it is time well spent. Be candid about the need for such time when making estimates about your schedule.

In summary, here a few general principles towards keeping a professional attitude towards your code:

Whether they're writing in Java, Tcl, Perl, or COBOL, programmers that follow these principles provide real value to their businesses and to the world.

References and Related Reading

Revision History

Document Revision # Action Taken, Notes When? By Whom?
0.1 Creation 11/20/2000 Bryan Quinn

acs-docs@arsdigita.com
Last modified: java.html,v 1.2 2001/01/21 01:49:34 bquinn Exp