The Infospheres Java Coding Standard
Version 1.3 - Date: 1999/08/11 08:10:53
By members of the Infospheres team at Caltech. Edited by Joseph Kiniry
(kiniry@acm.org) and Daniel M. Zimmerman (dmz@cs.caltech.edu).
Table of Contents
Introduction
Code standards aren't just about obsession, they are about productivity,
professionalism, and presentation. This code standard for Java is adhered to by
the Infospheres Group at Caltech so that our resulting product is more readable,
maintainable, robust, testable, and professional.
Many people helped with the evolution of this code standard. These practices
were not created in a vacuum. They are tried and true rules that have been used
in producing both research and commercial systems by teams of dozens of
programmers. While not all the rules are applicable to every developer or all
systems, a general adherence to the rules and a belief in software engineering
practices often results in happier and healthier developers and systems.
Structure
In the context of this document, "structure" means "organization, look, and
feel" of a body of code. It includes elements of system and subsystem
organization (packages), documentation (Javadoc tags, inline comments, and index
files), specification (more Javadoc tags, running comments, index files), and
development (code organization). Adhering to these standards means that every
piece of code has the same structure so that a reader can instantly know where
to find a piece of information (attribute, import, method, etc.) without have to
search through an entire source file.
Packages
Create a new Java package for each self-contained project or set
of related functionality, in accordance with the following package naming
guidelines (including a directory structure which corresponds to the package
naming, as per Java conventions):
- Globally unique package naming is obtained by building a package hierarchy
using the reversed domain name of your organization. Thus, all of our projects
fall under the
edu.caltech.cs package hierarchy.
- If a package is part of a larger project, make it a subpackage of a
reasonably-named top-level package. For example, code written for the CS141
class at Caltech might be placed in subpackages of
edu.caltech.cs.cs141 .
- If a package is personal code, rather than part of a larger project, place
it under the hierarchy named for your username within the domain. For example,
user "kiniry" would organize his code under the
edu.caltech.cs.kiniry hierarchy.
- Package names should be all lower-case.
- Package names should conform to existing Java examples when appropriate.
E.g., for I/O classes, make an
io package similar to
java.io . Other examples include java.lang ,
java.net , java.util , and java.math .
Provide a package.html file in each package directory briefly
outlining the purpose and structure of the package. This file is used by Javadoc
(in Java 1.2 and later) as package commentary, and also serves as local
documentation for your code tree. For more information on the format of this
file as used by Javadoc, see the package-level
comments documentation on Sun's web site. If you plan to allow local
browsing of your source tree, you should alias this file to
index.html so that it serves as the default index file for the
directory.
Program Files
Place each and every class in a separate file. This applies even to
non-public classes (which are allowed by the Java compiler to be placed in the
same file as the main class using them), except in the case of one-shot usages
where the non-public class cannot conceivably be used outside of its context.
One example of such usage is the creation of Event classes in AWT
1.1 programming.
Begin each file with a comment block containing at least the following
information (example below):
- The title of the project this package is associated with.
- Any copyright information relevant to the project.
- The RCS/CVS tag $
Id $, which identifies the file name, its
version, the user who last checked in the file, and the date the file was last
checked in.
- If the file contains more than one class, list the classes, along with a
very brief description of each.
- If the file introduces a principal entry point for a package, briefly
describe the rationale for constructing the package.
Immediately follow the file header with:
- The
package statement.
- The
import list, ordered according to the following rules:
- Core imports of the form "
import java.<packagename> "
are listed first; imports of standard Java extensions of the form
"import javax.<packagename> " are listed next; and all
remaining imports follow.
- Import lists (core, extension and other) are sorted in alphabetic order
independently.
- Avoid import lines which use the '*' construct (like "
import
java.io.* "). Using this construct makes it difficult to determine
exactly which classes are referenced by your class without detailed
inspection of the code.
Example file header:
/*
* The Infospheres Infrastructure, Version 1.0
*
* Copyright (C) 1996-1999 California Institute of Technology.
* All Rights Reserved.
*
* $Id: java_standard.html,v 1.38 1999/08/11 08:10:53 kiniry Exp $
*/
package edu.caltech.cs.infospheres.example;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Vector;
import info.net.MailDaemon;
import info.net.MailDaemonException;
import info.net.Message;
import info.net.Place;
import info.util.Debug;
Classes and Interfaces
Write all /** ... **/ comments using Javadoc conventions. Even
though it is not required by Javadoc, end each /** comment with
**/ to make it easier to read and check.
Preface each class with a /** ... **/ comment describing the
purpose of the class, guaranteed invariants, usage instructions, and/or usage
examples. The beginning of the comment should be a description of the class in
exactly one sentence. Also include any reminders or disclaimers about required
or desired improvements. Use HTML format when appropriate, but do not forget
that all inline text is parsed as HTML format, so accidental use of HTML
elements can result in strange looking documentation. See the below chart for
appropriate tags and usages.
Each class comment block must include exactly one @version tag
and at least one @author tag. The @author tags often
list everyone who has written more than a few lines of the class. Each
@author tag should list exactly one author. The
@version tag's version is a project specific string (e.g.
"1.0b5c7") followed by a CVS/RCS $Date $ tag. Additionally, each
class can optionally contain a // comment after its closing brace
stating that the class declaration has ended.
Example class comment block:
<file header, package name and imports, as above>
/**
* A class representing the archetypical class from which one can
* learn code standards through example.
*
* Usage example:
* <CODE>
* ArchetypeClass ac = new ArchetypeClass();
* ac.init();
* </CODE>
*
* @see ArchetypeAbstractClass
* @see ArchetypeInterface
* @see java.lang.Object
* @version 1.0b5c7 $Date: 1999/08/11 08:10:53 $
* @author Joseph R. Kiniry
* @author Daniel M. Zimmerman
**/
public class ArchetypeClass extends AnotherClass
implements FooInterface, BarInterface
{
...
}
// end of class ArchetypeClass
Class (Static)/Instance Fields
Use Javadoc conventions to describe the nature, purpose, constraints, and usage of static
fields and instance fields. See the chart below for appropriate tags and usages.
All static fields should appear together, before the set of method declarations;
all instance fields should likewise appear together, either before or after the
set of static fields (but always before the method declarations). The sets of
static and instance fields should be clearly offset by comments (the format of
these comments is left to the individual programmer, though they should be
clear). For example:
public class Example
{
// Static Fields
/**
* This is a static field.
**/
public static String staticString = "Static String";
// Instance Fields
/**
* This is an instance field.
**/
public String instanceString = "Instance String";
// Method Declarations
...
}
Methods
Method parameters should be cleanly organized, either on a single line or one
per line. All static methods should appear together; the same goes for instance
methods. These blocks of methods should be clearly delineated with comments (as
for blocks of variables, above). Some examples of acceptable method
declarations:
public static int aMethod(String aString, int anInt, double aDouble);
public synchronized Exception anotherMethod(String aString,
int anInt,
double aDouble);
public synchronized Event yetAnotherMethod
(Long aLongObject, String aString, Double aDoubleObject);
public synchronized static Class finallyTheLastMethod
(String aClassName,
Integer anIntegerObject,
Serializable[] anArrayOfSerializableObjects);
Use Javadoc conventions to describe nature, purpose, preconditions, effects, algorithmic
notes, usage instructions, reminders, etc. The beginning of a method comment
should be a summary of the method in exactly one sentence. Use HTML format when
appropriate. See the chart below for appropriate tags and usages.
In all of the following tags, Expression means
(OCL-Expression | code segment | natural language description) . An
OCL-Expression is an expression in the Object Constraint Language; see
Joe for more information. A code segment is a legal expression from any
programming language, but is most often written in the language of the code it
documenting, in this case Java. A natural language description is a
description written in a spoken language (like English).
For all tags, entities enclosed in () or <>
must be so enclosed when using the tags. E.g. "(Expression)" means literally "("
+ the expression + ")". Entities enclosed in [] in the table
indicate optional entities and should not use literal square brackets.
The table lists, in the "Usage" column, the Java entities to which each tag
is applicable. Possible values for this column are classes,
interfaces, methods, fields (that is, instance fields
and static fields of a class or interface), all (which means "classes,
interfaces, methods and fields"), and special (special usages explained
in the "Purpose/Description" column).
More detailed information on the syntax of the standard Javadoc tags
described here (most notably, @see , {@link} and the
serialization-related tags) is available from Sun's Javadoc Home Page.
Javadoc Tag Conventions
Tag |
Usage |
Purpose/Description |
Meta-Information |
@author Full Name |
Classes, Interfaces |
Lists an author of the class or interface. The text has
no special internal structure. A doc comment may contain multiple
@author tags. A standard author tag includes only the full
name of the author and should not include other information (like an email
address, web page, etc.) unless absolutely necessary. |
@history Description |
All |
Describes how a feature has been significantly modified
over time. For each major change, the description should include: who made
it, when it was made (date and version), what was done, why it was done,
and a reference to the change request and/or user requirement that
resulted in the change being made. |
Pending Work |
@bug Description |
Classes, Interfaces, Methods |
Describes a known bug in the class or method. One tag
should be used for each bug. If a construct has a known bug, it should be
described. Omission of a bug description is considered as bad an offense
as the existence of the bug in the first place. |
@review Username - Description |
All |
Suggests/Reminds a reader that a particular block of
code still needs to be reviewed (by the named user) for some reason.
Typical reasons include the "something's not right here" syndrome,
boundary condition checks, not understanding an algorithm completely,
etc. |
@todo Username - Description |
All |
Describes some work that still needs to be accomplished
by the named user. Typical examples include optimizing algorithms, proving
correctness of new code, renaming fields or methods to conform to
standards, cleaning up code, etc. |
@idea Username [Classifier] -
Description |
All |
Describes an idea for something from the named user. The
optional <classifier> argument is for ad hoc categorization of
ideas. Typical examples include optimizing algorithms, proving correctness
of new code, renaming fields or methods to conform to standards, cleaning
up code, etc. |
Preconditions |
(@precondition | @pre) (Expression)
[<Throwable> -] [Description] |
Methods |
Describes a precondition which must be true before the
method can be safely invoked. One tag is used for each precondition. If a
precondition is violated Throwable is thrown. |
@requires (Expression)
Description |
All |
Describes assumptions about execution context. In
particular, describes any reliance on actions in other threads to
terminate or provide notifications. Requires expressions are
usually not expressible in code and cannot be tested at
runtime. |
Postconditions |
(@postcondition | @post) (Expression)
[<Throwable> -] Description |
Methods |
Describes a postcondition which is true after a method
has completed, successfully or not. If a postcondition is violated
Throwable is thrown. Postconditions that throw exceptions
interact with the standard Java exception mechanism and thus are described
in the @exception tag. One tag is used for each
postcondition. |
@ensures (Expression) Description |
Classes, Methods |
Specifies the semantics of an element's behavior and any
guarantees it makes. Ensures expressions are usually not
expressible in code and cannot be tested at runtime. |
@generates (Expression)
[Description] |
Classes, Methods |
Describes new entities (for example,
Threads ) constructed as a result of the execution of a method
or the instantiation of a class. |
@modifies (SINGLE-ASSIGNMENT | QUERY | Expression)
Description |
All |
Indicates the semantics of a construct as follows:
SINGLE-ASSIGNMENT indicates that the construct will be
set or operated upon exactly once. Once the variable is set or the
method is called, it will never be set or called again.
QUERY indicates that the construct is read-only and has
no side-effects.
Expression indicates that a method modifies an object
and describes how it does so. |
Invariants |
@invariant (Expression) [<Throwable>]
Description |
Classes, Interfaces, Methods |
Specifies a class, interface or method invariant. An
invariant is an expression which must evaluate to true whenever the entity
being described is in a stable state. An invariant expression
must evaluate to a boolean.
An object is defined as being in a stable state when either
(a) no threads of control are within the object or operating upon the
object, (b) a single thread of control is about to enter a method of the
object, or (c) a single thread of control is about to exit a method of the
object.
If an invarient is violated when an object is in a stable state, a
Throwable is thrown. |
Concurrency Control |
@concurrency (SEQUENTIAL | GUARDED | CONCURRENT |
TIMEOUT <value> <Throwable> | FAILURE <Throwable> |
SPECIAL) [Description] |
All |
Describes the concurrency strategy and/or approach taken
by (necessary for) the class/interface/method (field). The execution
context for a method should be described at this point. The meanings of
the possible parameters are as follows:
SEQUENTIAL means that callers must coordinate so that
only one call/access to the object in question may be outstanding at
once. If simultaneous calls occur, the the semantics and integrity of
the system cannot be guaranteed.
GUARDED means that multiple calls/accesses from
concurrent threads may occur simultaneously to one object in question,
but only one is allowed to commence; the others are blocked until the
performance of the first operation is complete. This is the behavior of
synchronized methods.
CONCURRENT indicates that multiple calls/accesses from
concurrent threads may occur simultaneously to the object in question.
All will proceed concurrently with correct semantics. Note that this is
the default mode of Java methods and fields, unless otherwise indicated.
TIMEOUT <value> indicates that if a call to this
method is blocked for a time period greater than or equal to
<value>, the exception <Throwable> will be thrown.
FAILURE means that if a call to the method is currently
underway, all additional calls with fail and the exception
<Throwable> will be thrown.
SPECIAL indicates that the method has concurrency
semantics that are not covered by the preceding three cases. Make sure
to explain the particulars of the method's semantics in sufficient
detail that the reader will be quite clear on your method's unusual
semantics.
A method lacking a concurrency tag is considered CONCURRENT. The
semantics description is optional on methods which are tagged as
SEQUENTIAL or GUARDED. In general, all methods should have concurrency
tags. |
Java Usage Information |
@param parameter-name [WHERE (Expression)]
Description |
Methods |
Describes a method parameter. The description may be
continued on the following line(s). The expression indicates restrictions
on argument values. Restrictions that result in exceptions, for example
IllegalArgumentException , should be indicated as such. In
particular, it is important to indicate whether reference arguments are
allowed to be null . There must be one @param tag
for each and every parameter to the method. |
@return Description |
Methods |
Describes a method's return value. The description may
be continued on the following line(s). If the method being documented is a
simple getter method (or similar), a @returns tag is still
necessary; however, in such a case, the actual method description may be
omitted (since the @returns tag completely describes the
method). |
@exception ExceptionClassName [IF (Expression)]
Description |
Methods |
Describes an exception which can be thrown by the
method, and the circumstances under which it is thrown. The exception is
linked to its class documentation. The guard indicates restrictions on
argument values. In particular, it is important to indicate whether
reference arguments are allowed to be null . There must be one
@exception tag for each and every exception declared to be
thrown by the method; in particular, if a RuntimeException
such as IllegalArgumentException is declared in the method
signature, it must be documented. It is generally a good idea to declare
in the method signature any runtime exceptions which are thrown as a
result of conditions controllable at compile-time (such as the method
being called in the wrong system state, or a lack of sufficient range
checking on passed argument values). |
Versioning |
@version Version-String
$Date $ |
Classes, Interfaces |
Denotes the version of the class. The text has no
special internal structure. A doc comment may contain at most one
@version tag. The @version tag normally refers
to the version of the software project which contains this class, rather
than the version of this particular class. |
@deprecated Reference to replacement
API. |
All |
Indicates that this API should no longer be used (even
though it may continue to work). By convention, the text describes the API
(or APIs) which replace the deprecated API. For example:
@deprecated Replaced by setBounds(int, int, int, int).
If the API is obsolete and there is no replacement, the argument to
@deprecated should be "No replacement". |
@since version-tag |
All |
Indicates the (release) version number in which this
feature first appeared. This version number, like that for
@version , is usually a project-wide version number rather
than a version number for the particular class in which the feature
appears. No @since tag is required for features which have
existed since the first version of the project. |
Inheritance |
@hides FullClassName.FieldName
[Description] |
Fields |
Indicates that a particular field hides a field in a
parent class. For example:
/**
* @hides java.util.Vector.elementCount
**/
protected long elementCount = 0;
|
@overrides FullClassName.MethodName()
[Description] |
Methods |
Indicates that a particular method overrides a method in
a parent class. For example:
/**
* @overrides java.util.Vector.clone() We need to provide a deep clone.
**/
public synchronized Object clone();
If the overriding method does not either call or implement a
superset of the semantics of the method it overrides, its effects
must be documented (using precondition/postcondition/invariant
tags and the method description, as appropriate). |
Documentation |
@equivalent (Expression | Code
Reference) |
Classes, Interfaces, Methods |
Documents convenience or specialized methods which can
be defined in terms of a few operations using other methods. |
@example Description |
All |
Provides one or more examples of how to use a given
class, interface, method, or field. This helps developers to quickly
understand how to use your classes. |
@see APIName Label |
All |
Adds a hyperlinked "See Also" entry to the class
documentation. APIName can be the name of a Java API or an HTML anchor.
Some examples (with their appearance in Javadoc in comments on the
right-hand side) are:
@see java.lang // java.lang
@see java.lang.String // String
@see java.lang.String The String class // The String class
@see String // String
@see String#equals(Objetc) // String.equals(Object)
@see String#equals // String.equals(java.lang.Object)
@see java.lang.Object#wait(long) // java.lang.Object.wait(long)
@see Character#MAX_RADIX // Character.MAX_RADIX
@see <A HREF="spec.html">Java Spec</a> // Java Spec
This Javadoc tag is often used to reference an external document which
describes pertinent business rules or information relevant to the source
code being documented.
The character # separates the name of a class from the name of one of
its fields, methods, or constructors. One of several overloaded methods or
constructors may be selected by including a parenthesized list of argument
types after the method or constructor name. Whitespace in
@see 's classname is significant. If there is more than one
argument, there must be a single blank character between the arguments.
For example:
@see java.io.File#File(java.io.File, java.lang.String)
A doc comment may contain multiple @see
tags. |
{@link APIName Label} |
All |
Adds an inline link to other documentation. This tag
begins and ends with curly braces to seperate it from the rest of the
inline text. It accepts exactly the same syntax for APIName
and Label as the @see tag. A doc comment may
contain multiple {@link} tags. |
Design |
@design Description |
All |
Provides information about design decisions you have
made and/or useful things to know about parts of your code. |
Serialization |
@serial Description |
Special |
Describes the purpose of and acceptable values for a
seriable field. This tag can only be used on default serializable fields
(instance fields, of classes which implement Serializable ,
which are not declared to be transient ). There is no specific
format for the description. This information is used by Javadoc to build
pages describing the serialization behavior of the class. |
@serialField Field-Name Field-Type
Description |
Special |
Documents an ObjectStreamField component of
the serialPersistentFields member of a
Serializable class. This tag can only be used for such
components, and one tag should be used for each. The "Field-Name" and
"Field-Type" fields should be the name and class of the field,
respectively; there is no specific format for the description. This
information is used by Javadoc to build pages describing the serialization
behavior of the class. |
@serialData Description |
Special |
Documents the sequences and types of data written by the
class's writeObject and/or writeExternal methods
as part of object serialization. This tag can only be used in the doc
comments for the writeObject , readObject ,
writeExternal , and readExternal methods. This
information is used by Javadoc to build pages describing the serialization
behavior of the class. |
Dependencies |
@references (Expression)
[Description] |
Classes, Methods, Fields |
Indicates that the class or attribute references other
constructs like objects, instances, files, etc. This is primarily used to
indicate subtle interdependencies between classes, instances,
etc. |
@uses (Expression) [Description] |
All |
Indicates exactly which elements are utilized by this
element. This tag is primarily used to indicate hidden
dependencies. |
Miscellaneous |
@guard (Expression) [Description] |
Methods |
Indicates that actions use guarded waits
until the condition specified in Expression
holds. |
@values (Expression)
[Description] |
Fields |
Describes the possible values of a field, including
ranges and/or distinct values. |
@complexity (Expression)
[Description] |
Methods |
Documents the time or space complexity of a method.
Expression should be in big-O notation, but doesn't have to use proper
Java syntax. E.g. O(n*n) and O(n^2) are equivalent, but the second is the
more normal way to express a square term. Normally the free terms of the
expression are documented in the description and are usually related
directly to instance variables of the surrounding or related
class. |
Always be as precise as reasonably possible in documenting effects.
Code Layout
A consistent code layout style improves code readability, maintainability,
and robustness. We use emacs for automatic code layout. Our code layout
rules are as follows:
- Indention consists of spaces only (in particular, no tab characters are
allowed).
- Each indent level is exactly two spaces.
- Method declarations are seperated from the comments of the following
method by exactly two lines of white space.
- Comments are separated from method, field and class declarations by
exactly one line of white space.
- Complex expressions are fully parenthesized, for readability and clarity.
- Left-brace ("
{ ") placement occurs at the beginning of the
next line of code in all cases (including empty blocks). Code follows on the
next line, indented by two spaces. The emacs code block provided below
guarantees this indentation behavior. For example:
for (int i = 0; i < 100; i++)
{
// this is where the code begins
a = i * i;
}
- Braces are vertically aligned to highlight code blocks.
- Each long and/or complex code block should have its closing brace
commented to clearly identify the block being closed by the brace.
- The maximum line length is 78 characters.
- Spill-over indentation for breaking up long lines is allowed (and, in
fact, encouraged).
- All class fields are declared at the top of the class.
- Methods should be declared in the following order: constructors,
finalizers, initializers, static methods, then blocks of public instance
methods with their private helper methods. The exception to this is static
initializers, which should appear in between the static and instance fields.
- All binary operations (+, /, *, etc.) and assignments should be buffered
by a single space. Unary operations (like -, !, and ++) should not be
separated by their operands. For example:
double x = (y + z);
double a = (Math.pow(x) * (1.23 + 4.56)) * 2.0;
a += 3.1415;
x++;
boolean b = !(a == 1.0);
- Guard expressions in conditionals and loops should be separated from their
keywords by exactly one space. Moreover, brackets should always be used for
conditional and loop blocks, even those which consist of a single instruction.
For example:
for (int x = 1; x < 100; x++)
{
// do something
if (x == 2)
{
// a single line of code
}
while ((x % 2) == 0)
{
// multiple lines
// of code
}
switch (x)
{
case 1:
{
// some code
}
default:
{
// more code
}
}
}
- Static and instance fields should be organized (within their blocks) in
the following order:
public , protected ,
private .
Emacs-specific Code Standard Support
The following elisp code expressions can be added to your .emacs
startup file to institute all of the above standards (except the brackets for
every block of code in a conditional or loop) automatically. Note that, in fact,
it is actually much safer just to take someone's working .emacs
file and customize it for yourself. This way, subtle dependencies in the setup
are handled. Or, if you are local to the Caltech Computer Science file system,
you can just insert this line into your .emacs file:
(load-file "/ufs/info/lib/emacs_common/site-lisp/site-start.el")
Here is the elisp code:
;; Indentation Settings
;; preload cc-mode to make settings
(require 'cc-mode)
;; indents are in blocks of two spaces
(setq-default c-basic-offset 2)
;; make sure we don't use tabs in indents
(setq-default indent-tabs-mode nil)
(cond ((or (string-match "4." c-version)
(string-match "5." c-version))
;; Setup for CC-mode version 4 and above.
;; Set up indention for programming in C, C++, Objective C, and
;; Java
(defun c-lineup-javadoc-comments (langelem)
;; Define a new custom indentation function for handling
;; Javadoc comments. Line up all first *'s. First create a
;; new context so the point, mark, and current buffer are not
;; munged, even in the case of abnormal exit.
(save-excursion
;; goto the point that is defining our indention depth
(goto-char (cdr langelem))
;; is it the first line of a javadoc comment?
(if (looking-at "/\\*")
;; yes! so return a 1
1
0)))
;; We define a new CC-mode style for our group's code standards.
;; We'll call this style "caltech-java".
(defconst caltech-java-style
'((c-basic-offset . 2)
(c-comment-only-line-offset . (0 . 0))
(c-offsets-alist .
((access-label . 0)
(arglist-close . c-lineup-arglist)
(arglist-intro . c-lineup-arglist-intro-after-paren)
(c . c-lineup-javadoc-comments)
(case-label . +)
(inher-cont . c-lineup-java-inher)
(inline-open . 0)
(knr-argdecl-intro . 5)
(label . +)
(statement-case-open . +)
(statement-cont . 0)
(substatement-open . 0)
(statement-block-intro . +)
(topmost-intro-cont . +)))))
;; Customizations for all c-mode, c++-mode, objc-mode, and java-mode.
(defun caltech-java-mode-hook ()
"Hooking in the Caltech Infospheres code standard for CC-mode
version 4 and turning on cc mode's minor modes."
;; Add caltech-java style and set it for the current buffer.
(c-add-style "caltech-java" caltech-java-style t)
;; Add any user-specific customizations here (should be none).
;;
;; CC Mode has two minor modes; auto-newline and hungry-delete.
;; If you don't like the behavior of either of these minor modes,
;; comment out the following expression. More information on
;; these minor modes is available in the CC Mode info pages.
(c-toggle-auto-hungry-state 1)
;; Keybindings for all supported languages can be added here.
;; We can upt these in c-mode-map because all the other maps
;; inherit from it.
;; (define-key c-mode-map )
)
;; Add hook to Java mode to start everything up everytime we
;; enter a Java buffer.
(add-hook 'java-mode-hook 'caltech-java-mode-hook))
((string-match "3." c-version)
;; Customization for CC-mode version 3.
))
Documentation
What's the point?
Documentation is all about communication. If you have any hope or desire to
see your code understood and reused, it needs to be completely and thoroughly
documented. We have a tool called the "Comment Counter" which can actually
evaluate the true comment volume of your code. While we'll accept code
submissions with a 35% documentation ratio, around 50% is what we're really
looking for.
How much is enough?
Your guiding metric for "How much is enough?" should be the following:
Communicate exactly enough information in your comments to the reader so that
they could implement what you are describing and do so correctly.
Self-documenting code
Some argue that the code itself should be "self-documenting". This is true,
in some sense, and we enforce it in some ways through naming conventions and
running comments, but it isn't enough. What about the reader who doesn't know
the language you are coding in? What about proprietary reusable components?
Obviously, something more is necessary.
Real coders don't document
Also, for those of you that think that documenting is for weaklings and that
real hackers/masters/Rambo-coders don't need comments; believe us, we could find
some code that you wouldn't understand even with days of head-scratching (if
you're in the area, drop by and we'll prove it). Rambo-coders need not apply.
Local declarations, statements, and expressions
Use /* ... */ comments only to temporarily comment out blocks of
code. Otherwise, only C++-style (// ) comments should be used to
describe algorithmic details, notes, and related documentation which spans more
than a few code statements.
Example:
// Strategy:
// 1. Find the node
// 2. Clone it
// 3. Ask inserter to add clone
// 4. If successful, delete node
Use running // comments to clarify non-obvious code. However,
always prefer making the code more obvious to commenting it because it is
non-obvious, and don't bother commenting obvious code.
Example:
int index = -1; // -1 serves as flag meaning the index isn't valid
Or, even better:
static final int INVALID= -1;
int index = INVALID;
Embedded HTML Tags
We are embedding HTML tags in the source code as a first-order solution to
linking to regular (a la Javadoc) and arbitrary places in the code. Javadoc tag
conventions should be adhered to. Here are some example NAME tags:
<A NAME="HostManager#_top_"></A> - the top of the
class file.
<A NAME="instance_fields"></A> - begins the set
of instance fields of a class.
<A NAME="debug"></A> - an instance field of a
basic type.
<A NAME="hostLocation"></A> - an instance field
of non-basic type.
<A NAME="constructors"></A> - begins the set of
constructors of a class.
<A NAME="HostManager"></A> - the default
constructor. The first instance of a method in a class should be documented
with a anchor of this form (i.e. lacking any parameters at all). Thus, the
first constructor of every object should have at least two anchors, one like
this example and one similar to one of the following two examples. See the
example classes for more anchor examples.
<A NAME="HostManager()"></A> - the default
constructor.
<A NAME="HostManager(int)"></A> - a constructor
with a single base-type parameter.
<A NAME="instance_methods"></A> - begins the set
of instance methods of a class.
<A NAME="init"></A> - a method with no
parameters.
<A NAME="init()"></A> - a method with no
parameters (the same method as the previous example).
<A NAME="createObject(java.lang.String,
java.lang.String)"></A> - a more complex method with non-base
type parameters.
<A NAME="main(java.lang.String[])"></A> - the
main method of a class and an example of an array parameter.
<A NAME="algorithm_1"></A> - a arbitrary tagged
block (tag is arbitrary)
Embedded tags can either be placed in comment lines of their own or can be
embedded in Javadoc comment blocks.
Naming Conventions
You can name your temporary and loop variables anything you like, (we suggest
prefixes of temp and loop), but all your other variables, especially
static and instance fields of your objects, must have some sort of uniform
naming scheme. The follow specification of naming standards follows the
conventions of several organizations and individuals. It has been created by
committee, however, so it probably won't completely satisfy or dissatisfy any
individual.
Element Type |
Convention |
Examples and Comments |
Package |
All lowercase |
Use the recommended domain-based conventions described
in the Java
Language Specification, page 107 as prefixes. (For example,
edu.caltech.cs.infospheres .) |
File |
Compiler-enforced |
The java compiler enforces the convention that file
names have the same base name as the public class they
define. |
Class |
Capitalize all subwords |
DjinnMaster, BillTheCat, MyClass,
PokerPlayer |
Abstract Class |
Same as Class, but starting with
Abstract |
AbstractDjinn, AbstractCat, AbstractClass,
AbstractPlayer |
Factory Class |
Same as Class, but ending with
Factory |
DjinnFactory, CatFactory, ClassFactory,
PlayerFactor |
Class Implementation |
Same as Class, but ending with
Impl |
DjinnImpl, CatImpl, ClassImpl, PlayerImpl |
Exception |
Same as Class, but ending with
Exception |
DjinnException, CatException, ClassException,
PlayerException |
Interface |
Same as Class, but ending with Interface or
-able suffix |
DjinnInterface, CatInterface, Runnable,
RemoteLoadable |
Constant |
All capital letters with embedded underscores |
DJINN_MAX_WEIGHT, CAT_FUR_LENGTH, CLASS_SIZE,
PLAYER_NUM_FINGERS |
Instance Field |
Initial letter is lowercase, all other subwords are
capitalized. Attempts to embed or otherwise indicate type in the field
name are looked favorably upon. |
DjinnName djinnName, BillTheCat bill, Class myClass,
PokerPlayer aPlayer |
Method |
Initial letter is lowercase, remaining subwords are
capitalized. |
callDjinn(), kickCat(), twiddleClass(),
pokePlayer() |
Converter Method |
Initial lowercase word is "to", remaining subwords are
capitalized. |
toGenie(), toTiger(), toAbstractClass(),
toBridgePlayer() |
Getters (methods that query state) |
Initial lowercase word is "get", remaining subwords are
capitalized and, if possible, are exactly the same as the name of the
instance field to which they relate. |
getDjinnName(), getCatColor(), getClassSize(),
getPlayerBank() |
Setters (methods that set state) |
Initial lowercase word is "set", remaining subwords are
capitalized and, if possible, are exactly the same as the name of the
instance field to which they relate. |
setDjinnLocation(), setCatSex(), setClassLoader(),
setPlayerLuck() |
Recommendations
The recommendations have been moved to a separate document.
Tools
Emacs
The canonical summary: Emacs is the extensible, customizable,
self-documenting real-time display editor.
(Rewritten from the XEmacs home page) Emacs is a powerful,
extensible text editor with full GUI and terminal support.
Two primary supported free implementations of Emacs exist:
- FSF Emacs, the Free Software
Foundation's mainline Emacs implementation, and
- XEmacs, a highly graphical version
initially based on an early version of GNU Emacs 19 from the Free Software
Foundation and since kept up to date with recent versions of that product.
XEmacs stems from a collaboration of Lucid, Inc. with Sun Microsystems, Inc. and the University of Illinois, with additional
support having been provided by Amdahl
Corporation and Altrasoft.
Extending Emacs. (X)Emacs is extended through the use of
Emacs LISP packages. The
primary packages we use for the development of Java are as follows (this list is
by no means complete and reflects our personal biases):
- CC-mode. This is a GNU Emacs mode for editing files
containing C, C++, Objective-C, Java, and CORBA IDL code. CC-mode support
template insertion, auto-indenting, key shortcuts for often used expressions
and blocks and much, much more. Documentation on cc-mode can be found in the
info pages of your emacs process (type control-h then 'i').
- fill-paragraph. The fill-* functions reformat sections of
text, code, etc. to be more readable. I.e. They can automatically reorganize
and/or justify your code, text, HTML, etc. to fit your needs. The primary use
of fill-paragraph while coding in Java is cleaning up documentation in
comments. Most programmers do not like what it does to their source code by
default.
- The OO Browser. OOBR, the object-oriented browser, used
to be a free piece of software from Bob Weiner. It is/was a very powerful,
flexible, multi-language, source code browser (a la the Smalltalk tradition)
for Emacs. It is now a commercial product. Contact Altrasoft for more information.
- JDE: The Java Development Environment for Emacs. (from
the JDE home page): The JDE is an
Emacs Lisp package that provides a highly configurable Emacs wrapper for
command-line Java development tools, such as those provided in JavaSoft's JDK.
The JDE provides menu access to a Java compiler, debugger, and API documenter.
The Emacs/JDE combination adds features typically missing from command-line
tools, including:
- syntax coloring
- auto indentation
- compile error to source links
- source-level debugging
- source code browsing
The JDE supports both Emacs (Unix and Windows versions) and XEmacs. It is
freely available under the GNU public license. (Ed. note --- note that
much of the functionality of JDE is simply JDE using other packages like
cc-mode, font-lock-mode, etc. It does pull all of these packages together very
well.)
- Tags. (from XEmacs info documentation node (xemacs)Tags:)
A "tags table" is a description of how a multi-file program is broken up into
files. It lists the names of the component files and the names and positions
of the functions (or other named subunits) in each file. Grouping the related
files makes it possible to search or replace through all the files with one
command. Recording the function names and positions makes possible the `M-.'
command which finds the definition of a function by looking up which of the
files it is in.
Briefly, using tags with Java means that your emacs knows the location and
completion of all interesting features (classes, interfaces, fields, methods,
etc.) of your project so that you can (a) jump right to the feature
definitions, (b) use completion (see the next bullet), (c) do regular
expression searches and/or replaces on tags (e.g. global replace of a
variable), and more. See the documentation on tags in Emacs info for more
information on the use of tags.
- Completion. When using tags or OOBR, completion
can be enabled. When enabled, completion will let emacs complete partially
typed names of interesting features like classes, interfaces, methods, etc. No
longer do you have to type those 30 character interface names! Emacs does it
for you! Do an emacs apropos search on "completion" (control-h 'a') for more
information. Completion is normally mapped to meta-tab in most modes.
(Completion can work even in text mode - it can complete from your local
dictionary!)
- font-lock-mode. When Font Lock mode is enabled, text is
fontified (i.e. put into new fonts, colors, styles, etc. depending upon what
you are typing to make the display of information more clear) as you type it.
While font locking can make for a more pretty/clear display, it can seriously
slow down typing/development for large files and long-lived emacs sessions.
Possible solutions include refining font locking (see
turn-on-fast-lock and related functions), Lazy Font Locking (see
lazy-shot-mode ), caching font lock information (see
fast-lock-cache-directories ), and more.
- Jacob - The Java Commando Base. Jacob is a
Java class browser and project manager for Emacs and includes a powerful class
wizard. Jacob is a Java program and its functionality overlaps with
that of JDE, OOBR, and XEmacs. We find it most useful to use all of these
tools in tandem, adjusting to fit personal taste.
CommentCounter
CommentCounter is a small component which helps you to determine how well you
are commenting your Java code.
CommentCounter counts the lines of code and comments in a Java file or set of
Java files. Whitespace comments and code lines are not counted, nor are lines of
code less than 3 characters long (such as lines with only a solitary brace). The
totals for lines of code, lines of comments, and a ratio (comments/total) are
written to standard output.
Our position on code commenting is as follows:
- Horribly commented code averages 0-5% comment ratio.
- Poorly commented code has a 5-10% comment ratio.
- Average code has a 10-15% comment ratio.
- Good code has a 15-25% comment ratio.
- Excellent code has a > 25% comment ratio.
The code that we release averages approximately a 45% comment ratio. More
information on CommentCounter is available via the Infospheres releases web page
at http://www.infospheres.caltech.edu/releases/.
JPP: The Java Pre-Processor
Abstract.
The Java Pre-Processor, or JPP for short, is a parsing preprocessor for the
Java programming language. Unlike its namesake (the C/C++ Pre-Processor, cpp),
JPP provides functionality above and beyond simple textual substitution. JPP's
capabilities include code beautification, code standard conformance checking,
class and interface specification and testing, and documentation generation.
More information on JPP is available via the JPP home page at http://www.infospheres.caltech.edu/releases/jpp/.
The following is a brief overview of JPP.
Introduction.
The Java Pre-Processor, referred to as JPP henceforth, is a parsing
preprocessor for the Java 1.X programming language. This document will describe
the design, development, and use of JPP.
JPP is primarily used as either a front-end for a Java compiler like javac,
espresso, or guavac, or as a verification and validation tool as part of a
configuration management system. We will describe both possibilities here as
well as provide a number of examples of innovative alternative uses.
The default JPP configuration corresponds to the Infospheres Java Coding
Standard (this document). Any questions as to the details of code standards,
layout, beautification, and verification are addressed in that document. This
document only focuses on the tool JPP.
All aspects of JPP are user configurable. Configuration is accomplished
through the use of Java properties and command-line switches.
Briefly, JPP provides the following functionality:
- Code Beautification. JPP can process any legal Java code and reorganize it
in an ordered, aesthetic manner. The rules used in the reformatting of code
are user configurable. JPP is used as a code beautifier to clean up downloaded
or otherwise adopted code before performing a code review. It is also used in
preparation for gaining and understanding of a codebase before modifying and
maintaining it. Finally, JPP can be used to process code from multiple
developers/teams regularly to enforce local coding standards.
- Code Evaluation. JPP can also be used to take an existing piece of code
and ``grade'' it. Such a code evaluation comes in several forms:
- Code Standard Conformance Checking. JPP is configured to a specific code
standard. Code standards give rules on how code is syntactically arranged,
field naming policies, feature access rules, etc. JPP can evaluate how well
a piece of code conforms to its current code standard. Such an evaluation
comes in the form of a short or long report which can be automatically
mailed to the appropriate parties and/or logged for review.
- Code Complexity Analysis. JPP knows several standard code complexity
algorithms. JPP can evaluate Java classes, interfaces, and even whole
packages and provide complexity measures. These metrics can help guide a
designer and developer toward more readable, understandable, and
maintainable code. Metrics are also provided as short or long reports.
- Documentation Analysis. JPP can evaluate the thoroughness of code
documentation. JPP knows what a ``real'' comment is and performs information
theoretical complexity measures (per-feature and per-entity entropy) of
comments to determine their completeness and usefulness. JPP will comment on
your comments!
- Object-Oriented Design Principles. JPP understands a core set of
object-oriented design principles: the Laws of Demeter,
class/interface/inheritance dependency graph analysis, JavaBean patterns,
and component specification to name a few. JPP can evaluate Java code and
provide suggestions as to how to improve design based upon these principles.
- Class and Interface Specification. JPP's specification constructs are
inspired by Meyer's Design by Contract. The primary constructs used to specify
a contract for a component are method preconditions and postconditions, and
class invariants. JPP can enforce and/or encourage the specification of
contracts on the methods of classes and interfaces, and can test for the
validity of such clauses in subtyping relationships.
- Class and Interface Testing. In addition to the aforementioned contract
specifications on methods, JPP supports the specification of loop invariants
and variants. All five of these constructs (the three specification clauses
and the two loop clauses) can be transformed by JPP into actual embedded test
harness code, inserted into a class's methods at the appropriate points. The
insertion of the test code at compile time, and the enabling and disabling of
test code at run-time, is completely under the control of the developer.
- Documentation Generation. JPP can also transform Java code into HTML, XML,
or LaTeX for direct code documentation and reference. The resulting document
is properly formatted for pretty-printing, has the appropriate embedded links
for feature cross-referencing, and external language-specific links can be
embedded in the code with special directives to the preprocessor.
JPP is an evolving tool. If you have suggestions or bug reports, please email
the authors at jpp@unity.cs.caltech.edu.
IDebug: An Advanced Debugging Framework for Java
Abstract.
IDebug, the Infospheres debugging framework, is an advanced debugging
framework for Java. This framework provides the standard core debugging and
specification constructs such as assertions, debug levels and categories, stack
traces, and specialized exceptions. Debugging functionality can be fine-tuned to
a per-thread and/or a per-class basis, debugging contexts can be stored to and
recovered from persistent storage, and several aspects of the debugging run-time
are configurable at the meta-level. Additionally, the framework is designed for
extensibility. Planned improvements include support for debugging distributed
object systems via currying call stacks across virtual machine contexts and
debug information logging with a variety of networking media including unicast,
multicast, RMI, distributed events, and JavaSpaces. Finally, we are adding
support for debugging mobile agent systems by providing mobile debug logs.
More information on IDebug is available via the IDebug home page at http://www.infospheres.caltech.edu/releases/idebug/.
The following is a brief overview of IDebug.
Introduction.
IDebug, the Infospheres debugging framework, is implemented as a set of Java
Beans (Java components) collected into the package IDebug. These classes can be
used either (a) as ``normal'' classes with standard manual debugging techniques,
or (b) as components within visual Java Bean programming tools.
This package provides many standard core debugging and specification
constructs, such as the previously discussed assertions, debug levels and
categories, call stack, and specialized exceptions. Debug levels permit a
developer to assign a ``depth'' to debug statements. This creates a lattice of
information that can be pruned at runtime according to the demands of the
current execution. Call stack introspection is provided as part of the Java
language specification. The IDebug framework uses the call stack to support a
runtime user-configurable filter for debug messages based upon the current
execution context of a thread. Finally, a set of specialized exceptions are
provided for fine-tuning the debug process.
Additionally, the framework supports extensions for debugging distributed
systems. One problem typical of debugging distributed systems is a loss of
context when communication between two non-local entities takes place. E.g. When
object A invokes a method m on object B, the thread within m does not have
access to the call stack from the calling thread in A. Thus, the IDebug package
supports what we call call stack currying. Information such as source object
identity, calling thread call stack, and more is available to the debugging
framework on both sides of a communication. Such information can be curried
across arbitrary communication mediums (sockets, RMI, etc.).
The IDebug package is also being extended to support the debugging of mobile
agent systems. Mobile agent architectures can support disconnected computing.
For example, an object O can migrate from machine A to machine B, which might
then becomes disconnected from the network (i.e. absolutely no communication can
take place between B and A). Since B cannot communicate with A, and printing
debugging information on B's display might not be useful or possible, B must log
debugging information for later inspection. To support this functionality, the
IDebug package will provide serializable debug logs. These logs can be carried
around by a mobile object and inspected at a later time by the object's owner or
developer.
The IDebug package is very configurable. Debugging functionality can be
fine-tuned on a per-thread basis. Each thread can have its own debugging
context. The context specifies the classes of interest to that particular
thread. I.e. If a thread T specifies that it is interested in a class C but not
a second class D, then debugging statements in C will be considered when T is
inside of C, but debugging statements in D will be ignored at all times. These
debugging contexts can be stored to and recovered from persistent storage. Thus,
``named'' special-purpose contexts can be created for reuse across a development
team.
IDebug is an evolving tool. If you have suggestions or bug reports, please
email the authors at idebug at unity.cs.caltech.edu.
|