Hacking


ADK coding standards

Hes Siemelink

Programming languages are wonderfully complex tools to specify data structures and algorithms. Unfortunately, programming languages do not enforce a consequent input style. Although the syntax is well-defined, it allows chaotic code and layout. This makes some programs unreadable. This document introduces guidelines that will help you make your code more understandable to others and to yourself.

The compiler is not the only one who has to understand your code. Other people will sooner or later have to look into what you write.You may believe that object orientation enables us to encapsulate gory implementation details, but sooner or later somebody is going to work with your code. If only just to see how things were solved before starting a complete rewrite.

To this end, code must be readable. These web pages provide a way to code in consistent layout, making it easier to understand code.Index

In general, we adhere to the Sun’s Code Conventions. However, this document is not always clear or complete. And not all conventions render code as readable as it could be. Therefore at Tryllian we use a modified version. The structure of Sun’s document is followed.

1.Introduction
2.File Names
3.File Organization
4.Indentation
5.Comments
6.Declarations
7.Statements
8.White Space
9.Naming Conventions
10.Programming Practices
11.Tools & Jident
12.Further Reading
13.Code Example


  1. Introduction
    Every project needs coding standards to ensure that all contributors can read all of the source without being hampered by a wild and original variety of coding styles. The ADK is no exception. We have tried to follow Sun’s guidelines as close as possible, but here’s our take on them as written by one of the pioneers of the ADK, Hes Siemelink..
  2. File Names
    This section lists commonly used file suffixes and names.

2.1 File Suffixes
Java Software uses the following file suffixes:

File TypeSuffix
Java source.java
Java bytecode.class
XML file.xml
JBuilder project.jpr

2.2 Common File Names

File NameUse
makefile.jmkThe preferred name for makefiles. We use jmake to build our software.
package.htmlEach package must have a a HTML description. (Otherwise it won’t show up in the javadoc)
makefile.jmkMakefile for JMake build scripts
build.xmlMakefile for ANT build scripts

3. File Organization

A file consists of sections that should be separated by blank lines and a comment identifying each section. (See Sections)

Files longer than 2000 lines are cumbersome and should be avoided. If a file gets longer than that, consider splitting the class into subcomponents.3.1 Java Source Files

Each Java source file contains a single public class or interface. When private classes and interfaces are associated with a public class, you can put them in the same source file as the public class. The public class should be the first class or interface in the file.

Java source files have the following ordering:

1.Beginning comments
2.Package and Import statements
3.Class and interface declarations

3.1.1 Beginning Comments

All source files should begin with a c-style comment that lists the class name, version information, date, and copyright notice:

/* * Classname * * Version information * * Date * * Copyright notice */

Note: At Tryllian we do not use the beginning comments (yet).

3.1.2 Package and Import Statements

The first non-comment line of most Java source files is a package statement. After that, import statements can follow. For example:

package java.awt;

import java.awt.peer.CanvasPeer;

Package names are always written in all-lowercase ASCII letters. The first component of a unique package name should be one of the top-level domain names (com, edu, gov, mil, net, org or one of the two-letter codes identifying countries nl, fr, uk, …).


Ordering import statements

Import statements should be grouped in three sections:

1Java library imports
2Third-party imports
3Tryllian imports

Sections appear in this order. Each section is seperated by a blank line. Do not place blank lines within a section.


The import statements are ordered alphabatically.


Import classes seperately whenever you can. Always import seperate classes from a package that is a collection of very different concepts, for example java.util. So

import java.util.Calender
import java.util.Vector

is preferred over

import java.util.*;

Do not hesitate to add comments.

Complete example (from the class ConnectionManager in the package com.tryllian.agent.net)

package com.tryllian.agent.net;

import java.io.*;
import java.net.*;
import java.security.*;
import java.util.*;
import java.text.*; // To parse dates

import iaik.security.ssl.*;

import com.tryllian.agent.Agent;
import com.tryllian.agent.Location;
import com.tryllian.agent.Owner;
import com.tryllian.agent.UniverseConstants;
import com.tryllian.util.*;

Package names may also start with just ‘tryllian’. E.g. tryllian.afc.task.

3.1.3 Class and Interface Declarations

The following table describes the parts of a class or interface declaration, in the order that they should appear.

Part of Class/Interface DeclarationNotes
1Class/interface documentation comment (/**...*/) 
2class or interface statement 
3Class/interface implementation comment (/*...*/), if necessaryThis comment should contain any class-wide or interface-wide information that wasn’t appropriate for the class/interface documentation comment.
4Class (static) variablesFirst the public class variables, then the protected, then package level (no access modifier), and then the private.
5Instance variablesFirst public, then protected, then package level (no access modifier), and then private.
6Constructors 
7MethodsThese methods should be grouped by functionality rather than by scope or accessibility. For example, a private class method can be in between two public instance methods. The goal is to make reading and understanding the code easier.

See the Comment section on what to write in the class comments.

 

Formatting

If a class just extends another class, use the following format for the class declaration:

public class MyClass extends SuperClass {

   // Implementation…
}

But use the following layout if the class also extends one or more interfaces:

public class MyClass
       extends SuperClass
       implements OneInterface,
                  AnotherInterface
{

   // Implementation…
}

Keep the following order in your class:

1.Final static constants
2.Static class variables
3.Member variables
4.Constructors
5.Methods
6.Inner classe

Sections

Group methods into logical groups. Always keep all implementating methods of an interface together. Seperate groups with border marking comments. These comment spread over three lines, start with //, are not indented and only have text on the middle line.
For example:

...
//
// Implementation of SimpleStack interface
//
    public void push(Object o) {
       // ...
    }

    public Object pop() {
       // ...
    }
//
// Inner classes
//

    private class StackElement {

        // ...    }
...


4. Indentation

INDENTATION IS FOUR (4) SPACES,
DO NOT USE THE TAB CHARACTER!

Yes, that goes for you, too! Configure your IDE’s! All of them!

Additional Comments

4.1 Line Length

Do avoid lines longer than 80 characters, since they’re not handled well by many terminals and tools.4.2 Wrapping Lines

When an expression will not fit on a single line, break it according to these general principles:

Break after a comma
Break before an operator
Prefer higher-level breaks to lower-level breaks
Align the new line with the beginning of the expression at the same level on the previous line
Indent every wrapped line with an extra two spaces (half indent). This is clearer than regular or even double indent
Start curly brackets at the beginning of the line after a line wrap

f your absolutely clueless, let Jindent figure out how to break lines.

Here are some examples of breaking method calls:

someMethod(longExpression1, longExpression2, longExpression3,
longExpression4, longExpression5);

var = someMethod1(longExpression1,
someMethod2(longExpression2, longExpression3));

Following are two examples of breaking an arithmetic expression. The first is preferred, since the break occurs outside the parenthesized expression, which is at a higher level:

longName1 = longName2 * (longName3 + longName4 – longName5)

  • 4 * longname6; // PREFER

longName1 = longName2 * (longName3 + longName4

  • longName5) + 4 * longname6; // AVOID

Following are two examples of indenting method declarations. The first is the conventional case. The second would shift the second and third lines to the far right if it used conventional indentation, so instead it indents only two spaces:

// Conventional indentation
someMethod(int anArg, Object anotherArg, String yetAnotherArg,
Object andStillAnother) {

}

// Indent two spaces to avoid deep indents
// Put the curly bracket on the next line
private static synchronized horkingLongMethodName(int anArg,
Object anotherArg, String yetAnotherArg,
Object andStillAnother)
{

}

In the following example the if -statement is not clearly seperated from the body:

// Don’t use this indentation
if ((condition1 && condition2)
|| (condition3 && condition4)
||!(condition5 && condition6)) { // Bracket is lost in space
doSomethingAboutIt();
}

Use smaller indents instead and move the curly bracket to the next line to visually ‘close’ the statement:

// Wrap lines at half indents
if ( (condition1 && condition2)
  || (condition3 && condition4)
  ||!(condition5 && condition6))
{
    doSomethingAboutIt();
}

Vertically align similar expressions for a clearer image. For example, in the above example, alle variables starting with ‘condition’ are aligned in columns, which is more readable.

Here are three acceptable ways to format ternary expressions:

alpha = (aLongBooleanExpression) ? beta : gamma;

alpha = (aLongBooleanExpression) ? beta
: gamma;

alpha = (aLongBooleanExpression)
? beta
: gamma;


  1. Comments
    Java programs can have two kinds of comments: implementation comments and documentation comments. Implementation comments are those found in C++, which are delimited by //, and //. Documentation comments (known as “doc comments”) are Java-only, and are delimited by /*/. Doc comments can be extracted to HTML files using the javadoc tool.

Implementation comments are mean for commenting out code or for comments about the particular implementation. Doc comments are meant to describe the specification of the code, from an implementation-free perspective. to be read by developers who might not necessarily have the source code at hand.

Comments should be used to give overviews of code and provide additional information that is not readily available in the code itself. Comments should contain only information that is relevant to reading and understanding the program. For example, information about how the corresponding package is built or in what directory it resides should not be included as a comment.

Comments should not be enclosed in large boxes drawn with asterisks or other characters.
Comments should never include special characters such as form-feed and backspace.

Comments are clearer than code
There is a big misconception about the relation between code comments and program code. Most tutorials on programming languages state that code should be self-explanitory. In other words, good code supposedly doesn’t need comments. This is nonsense. Good comments are easier to understand than good code.

Look at the following example:

ButtonEnumeration buttons = this.getAllButtons();

while (buttons.hasMoreElements()) {

buttons.nextElement().setForeground(Color.green);

}

This particular piece of code is not difficult understand. However it is not immediately clear what it does.

Now look at the same code, where we have added a little comment header.

// Paint all buttons green
ButtonEnumeration buttons = this.getAllButtons();

while (buttons.hasMoreElements()) {

buttons.nextElement().setForeground(Color.green);

}

The comment explains the little block of code instantly and the green syntax highlighting of comments make it stand out from the rest.

Remember that you are never the exclusive owner of a source file. Other people will look at your code. So you’d better make your code easy to understand. And besides do you still understand something you’ve written last year?

Organize your code (method bodies) into logical chunks. Give each chunk an appropiate heading. Syntac highlighting enables others to quickly scan through the implementation. They get a sense of how the class is implemented by reading only the comments.

Example (from the class AgentConversation in the package com.tryllian.gossip.agent.tasks)

public void reason() {

// End conversation if the agent is done.
if (isTimeToEndConversation()) {

endConversation();

debug.println("Ending the conversation.");

succeedTask();

// Exit reasoner
return;

}

// Process incoming message
handleReceivedMessage(getKnowledge().getLastMessage());

// Clear message marker
getKnowledge().setLastMessage(null);

}

This commenting scheme is not mandatory but highly recommended. It may seem tedious to enter all those comments, but it really has a lot of advantages. Apart from improved readability, you will notice that once you start with it adding header comments to code chunks, it becomes easier to think about the operations a method body should perform. Specifying small operations in natural language helps you think in logical parts and defining them with more clarity.

5.1 Doc Comments
Doc comments describe Java classes, interfaces, constructors, methods, and fields. Each doc comment is set inside the comment delimiters /*/, with one comment per class, interface, or member. This comment should appear just before the declaration:

/**

  • The Example class provides …
    / public class Example { … Notice that top-level classes and interfaces are not indented, while their members are. The first line of doc comment ( /* ) for classes and interfaces is not indented; subsequent doc comment lines each have 1 space of indentation (to vertically align the asterisks). Members, including constructors, have 4 spaces for the first doc comment line and 5 spaces thereafter.

If you need to give information about a class, interface, variable, or method that isn’t appropriate for documentation, use a block comment immediately after the declaration. For example, details about the implementation of a class should go in in such an implementation block comment following the class statement, not in the class doc comment.

Doc comments should not be positioned inside a method or constructor definition block, because Java associates documentation comments with the first declaration after the comment.

For further details, see “How to Write Doc Comments for Javadoc” which includes information on the doc comment tags (@return, @param, @see):

http://java.sun.com/products/jdk/javadoc/writingdoccomments.html

For further details about doc comments and javadoc, see the javadoc home page at:

http://java.sun.com/products/jdk/javadoc/

5.1 Implementation Comment Formats
Apart from javadocking, there are four situations to use comments

1.Meta information
2.Code description
3.Code clarification
4.Disabling code

5.2.1 Meta information
Use block comments to provide descriptions of files, methods, data structures and algorithms. Block comments may be used at the beginning of each file and before each method. They can also be used in other places, such as within methods. Block comments inside a function or method should be indented to the same level as the code they describe.

A block comment should be preceded by a blank line to set it apart from the rest of the code.

/*

  • Here is a block comment.
    */
    You may omit the vertical bar of asterisks ( * ) marking javadoc and multiline block comments. A single asterisk is already one happy character and a whole string of them provides rather distracting visual clutter. Syntax highlighting should suffer. (Notice that even vi supports syntax highlighting!).

Start a block comment with /* (or /** if it’s javadoc). Start documentation on the next line. Use one indent unit (4 spaces!).

For example:

/** Comments can distract you if they are

  • rather long and have these pesky little
  • asterisks as a continuous stream of
  • epilepsy provoking elements at the left
  • side of your screen.
    */

/**
However, by elimanting them, a crisp and
clear block of text emerges, which is
a feast for the eyes, a beacon of tranquility
in the sea of ludicrous symbolic artifacts
that make up the grammar of a programming
language.
*/

Unfortunately, Jindent does not know this 🙁

5.2.2 Code description
Use // -style comments to say what a chunk of code is supposed to do. (As described above):

// Paint all buttons green
ButtonEnumeration buttons = this.getAllButtons();

while (buttons.hasMoreElements()) {

buttons.nextElement().setForeground(Color.green);

}

Start comments with a capital letter. Put a space between the comment sign and the first word. Use whole sentences:

//bad comment

// Small sentences are more readable. (This is good!)

5.2.3 Code clarification
Avoid end-of-line comments after a statement. Comments are almost always clearer if put above the line the comment is about.

So do not write:

while (agents.hasMoreElements()) { // Kill all agents

agents.nextAgent().die();

}

but rather:

// Kill all agents
while (agents.hasMoreElements()) {

agents.nextAgent().die();

}

However, there are some cases, you want to put // -comments on the same line as code. Those trailing comments should be used for short remarks. Put at least two spaces between the end of the statement and the comment. Align comments in the same code block. (But remember that header comments on the previous line are usually more effective.):

System.out.println(“Please Wait.”); // Notify user.

dataBase.put(object); // This may take a while.

5.2.4 Disabling code
From a maintenance point of view, disabling code by commenting it out is tricky business. There is a risk in getting a lava flow of dead comments. If you want to do it, you can use either /**/ block comments or // line comments. Put // comments at zero indentation, so disabled code stands out when scrolling through a file. This last style is preferred:

class MyClass {

private void someMethod() {

// System.out.println(“Debugging someMethod()…”);
// System.out.println(“Now calling doSomeElse()”);

doSomethingElse(); }

}


  1. Declarations

6.1 Number Per Line
Use one declaration per line since it is easier to maintain and encourages commenting. In other words,

int level; // Indentation level
int size; // Size of table
and not

int level, size; // Wrong!
And certainly do not put different types on the same line. Example:

int foo, fooarray[]; // Wrong!
The examples above use one space between the type and the identifier. A clearer alternative is to align declarations using spaces.

int level; // indentation level
int size; // Size of table
Object currentEntry; // Currently selected table entry

6.2 Initialization
Try to initialize local variables where they’re declared. The only reason not to initialize a variable where it’s declared is if the initial value depends on some computation occurring first.

6.3 Placement

Put declarations only at the beginning of blocks. (A block is any code surrounded by curly braces “{” and “}”.) Don’t wait to declare variables until their first use; it can confuse the unwary programmer and hamper code portability within the scope.

void myMethod() {

int int1 = 0;      // Beginning of method block

if (condition) {
    int int2 = 0;  // Beginning of "if" block
    ...
}

}
The one exception to the rule is indexes of for loops, which in Java can be declared in the for statement itself.

for (int i = 0; i < maxLoops; i++) {
// loop
}
Avoid local declarations that hide declarations at higher levels. For example, do not declare the same variable name in an inner block:

int count;

myMethod() {
if (condition) {
int count = 0; // Avoid!

}

}

6.4 Class and Interface Declarations
When coding Java classes and interfaces, the following formatting rules should be followed:

No space between a method name and the parenthesis "(" starting its parameter list
Open brace "{" appears at the end of the same line as the declaration statement
Closing brace "}" starts a line by itself indented to match its corresponding opening statement, except when it is a null statement the "}" should appear immediately after the "{"

class Sample extends Object {

int ivar1;
int ivar2;

Sample(int i, int j) {

    ivar1 = i;
    ivar2 = j;
}

int emptyMethod() {}

...

}
Use blank lines to separate almost anything.

6.5 Javadoc comments for member variables

It is recommended to provide a javadoc style comment for each declaration of a member variable (variables declared outside of methods). You may want to run javadoc over all your instance variables (including the private ones) and it looks consistent anyway.

/** Indentation level */
private int _level = 0;


  1. Statements

7.1 Simple Statements
Each line should contain at most one statement. Example:

argv++; // Correct
argc–; // Correct
argv++; argc–; // AVOID!
2 Compound Statements

Compound statements are statements that contain lists of statements enclosed in braces “{ statements }”. See the following sections for examples.

Indentation
The enclosed statements should be indented one more level than the compound statement.

Position of braces
The opening brace should be at the end of the line that begins the compound statement; the closing brace should begin a line and be indented to the beginning of the compound statement.

There are very good reasons to start the opening brace at the next line. Although people tend to get very emotional with this issue, we stick to the standard.

Do add an extra line after having started a block to make the code more readable.

public void someMethod() {
// AVOID first statements that ‘stick’ to the previous line.

// Code

}

public void someOtherMethod() {

// Let your implementation breath!
// Add blank lines to seperate logical chunks

// Code

}

You don’t have to add a blank line if the compound statement only contains one statement.

public boolean isTrue() {
return true;
}

Do not omit braces
Braces are used around all statements, even single statements, when they are part of a control structure, such as a if-else or for statement. This makes it easier to add statements without accidentally introducing bugs due to forgetting to add braces.

7.3 return Statements
A return statement with a value should not use parentheses unless they make the return value more obvious in some way. Example:

return;

return myDisk.size();

return (size ? size : defaultSize);

7.4 if, if-else, if else-if else Statements
The if-else class of statements should have the following form. Put the else on a new line:

if (condition) {
statements;
}

if (condition) {
statements;
}
else {
statements;
}

if (condition) {
statements;
}
else if (condition) {
statements;
}
else {
statements;
}
Note: if statements always use braces {}. Avoid the following error-prone form:

if (condition) // AVOID! This omits the braces {}!
statement;

7.5 for Statements
A for statement should have the following form:

for (initialization; condition; update) {
statements;
}
An empty for statement (one in which all the work is done in the initialization, condition, and update clauses) should have the following form:

for (initialization; condition; update);
When using the comma operator in the initialization or update clause of a for statement, avoid the complexity of using more than three variables. If needed, use separate statements before the for loop (for the initialization clause) or at the end of the loop (for the update clause).

7.6 while Statements
A while statement should have the following form:

while (condition) {
statements;
}
An empty while statement should have the following form:

while (condition);

7.7 do-while Statements
A do-while statement should have the following form:

do {
statements;
} while (condition);

7.8 switch Statements
A switch statement should have the following form. Indent the cases and add a blank line before the first case statement.

switch (condition) {

case ABC:
    statements;
    /* Falls through. */

case DEF:
    statements;
    break;

case XYZ:
    statements;
    break;

default:
    statements;
    break;

}

Every time a case falls through (doesn’t include a break statement), add a comment where the break statement would normally be. This is shown in the preceding code example with the ‘falls through’ comment.

Every switch statement should include a default case. The break in the default case is redundant, but it prevents a fall-through error if later another case is added.

7.9 try-catch Statements
A try-catch statement should have the following format. Start the catch (and finally) on a new line.

try {
statements;
}
catch (SomeException se) {
statements;
}

Name the exception variable by using the captial letters of the exception caught. Number variable names when catching more excpetions of the same type in the same scope.

A try-catch statement may also be followed by finally, which executes regardless of whether or not the try block has completed successfully.

try {
statements;
}
catch (ExceptionClass e) {
statements;
}
finally {
statements;
}

  • Avoid return, break or continue in finally clauses

8. White Space

DON’T BE AFRAID OF THE GREAT WHITE SPACE!

8.1 Blank Lines
Blank lines improve readability by setting off sections of code that are logically related.

Two blank lines should always be used in the following circumstances:

Between sections of a source file
Between class and interface definitions
One blank line should always be used in the following circumstances:

Between methods
Between the local variables in a method and its first statement
Before a block or single-line comment
Readability
Blank spaces should be added between logical sections inside a method to improve readability. Do not be conservative with blank lines! Use blank lines in combination with comment headers to identify logical chunks of code in a method body.

The following example is taken from AgentShapeIcon in the package com.tryllian.gossip.homeplatform.gui2. The method body contains of three steps: loading the file, creating a buffer image to paint on and painting the loaded image onto the buffer image. Note the usage of blank lines and the way long lines are split.

/**
Create a BufferedImage and fill it with the contents of an image file
*/
private BufferedImage getImage(String file) {

double scaleX;
double scaleY;
AffineTransform scale;

// Use javax.swing.ImageIcon to conveniently load a file.
ImageIcon tempImage =
  TryllianResource.getImageIcon("/data/" + file);

// Create BufferedImage
BufferedImage buffer = new BufferedImage(
  AgentShape.DEFAULT_WIDTH, 
  AgentShape.DEFAULT_WIDTH, IMAGE_TYPE
);

// Paint ImageIcon onto buffered image
Graphics2D g2 = buffer.createGraphics();

scaleX = (double) AgentShape.DEFAULT_WIDTH /
  tempImage.getIconWidth();
scaleY = (double) AgentShape.DEFAULT_WIDTH /
  tempImage.getIconHeight();
scale = AffineTransform.getScaleInstance(scaleX, scaleY);

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
g2.drawImage(tempImage.getImage(), scale, null);

g2.dispose();

return buffer;

}

8.2 Blank Spaces
Blank spaces should be used in the following circumstances:

A keyword followed by a parenthesis should be separated by a space. Example:
while (true) {

}
Note that a blank space should not be used between a method name and its opening parenthesis. This helps to distinguish keywords from method calls.

A blank space should appear after commas in argument lists.
All binary operators except . should be separated from their operands by spaces. Blank spaces should never separate unary operators such as unary minus, increment (“++”), and decrement (“–“) from their operands. Example:
a += c + d;
a = (a + b) / (c * d);

while (d++ = s++) {
n++;
}

printSize(“size is ” + foo + “\n”);
The expressions in a for statement should be separated by blank spaces. Example:
for (expr1; expr2; expr3)
Casts should be followed by a blank space. Examples:
myMethod((byte) aNum, (Object) x);
myMethod((int) (cp + 5), ((int) (i + 3)) + 1);


  1. Naming Conventions
    Naming conventions make programs more understandable by making them easier to read. They can also give information about the function of the identifier-for example, whether it’s a constant, package, or class-which can be helpful in understanding the code.

9.1 Packages
Package names are always written in all-lowercase ASCII letters. The first component of a unique package name should be one of the top-level domain names (com, edu, gov, mil, net, org or one of the two-letter codes identifying countries nl, fr, uk, …).

Subsequent components of the package name vary according to an organization’s own internal naming conventions. Such conventions might specify that certain directory name components be division, department, project, machine, or login names.

package com.tryllian.agent;
package edu.cmu.cs.bovik.cheese;
9.2 Classes
Class names should be nouns, in mixed case with the first letter of each internal word capitalized. Try to keep your class names simple and descriptive. Use whole words-avoid acronyms and abbreviations (unless the abbreviation is much more widely used than the long form, such as URL or HTML).

class Raster;
class ImageSprite;

9.3 Interfaces
Interface names should be capitalized like class names.

interface RasterDelegate;
interface Storing;

9.4 Methods
Methods should be verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized.

run();
runFast();
getBackground();

9.5 Variables
Except for variables, all instance, class, and class constants are in mixed case with a lowercase first letter. Internal words start with capital letters. Variable names should not start with underscore _ or dollar sign $ characters, even though both are allowed.

float myWidth;
Always spell out names. Do not use abreviations or funky phonetic numbers.

Object connectionManager;
Object connectMgr; // AVOID
int fromMeToYou;
int fromMe2U; // AVOID
Variable names should be short yet meaningful. The choice of a variable name should be mnemonic- that is, designed to indicate to the casual observer the intent of its use. One-character variable names should be avoided except for temporary “throwaway” variables. Common names for temporary variables are i, j, k, m, and n for integers; c, d, and e for characters.

int i;
char c;
9.6 Constants
The names of variables declared class constants and of ANSI constants should be all uppercase with words separated by underscores (“_”). (ANSI constants should be avoided, for ease of debugging.)

static final int MIN_WIDTH = 4;
static final int MAX_WIDTH = 999;
static final int GET_THE_CPU = 1;


  1. Programming Practices

10.1 Providing Access to Instance and Class Variables
Don’t make any instance or class variable public without good reason. Often, instance variables don’t need to be explicitly set or gotten-often that happens as a side effect of method calls.

Follow the JavaBeans standard: name getter and setter methods appropiately. (see Naming Conventions).

One example of appropriate public instance variables is the case where the class is essentially a data structure, with no behavior. In other words, if you would have used a struct instead of a class (if Java supported structs, then it’s appropriate to make the class’s instance variables public.

10.2 Referring to Class Variables and Methods
Avoid using an object to access a class (static) variable or method. Use a class name instead. For example:

classMethod(); // OK
AClass.classMethod(); // OK
anObject.classMethod(); // AVOID!

10.3 Constants
Numerical constants (literals) should not be coded directly, except for -1, 0, and 1, which can appear in a for loop as counter values.

10.4 Variable Assignments
Avoid assigning several variables to the same value in a single statement. It is hard to read. Example:

fooBar.fChar = barFoo.lchar = ‘c’; // AVOID!
Do not use the assignment operator in a place where it can be easily confused with the equality operator. Example:

if (c++ = d++) { // AVOID! (Java disallows)

}
should be written as

if ((c++ = d++) != 0) {

}
Do not use embedded assignments in an attempt to improve run-time performance. This is the job of the compiler. Example:

d = (a = b + c) + r; // AVOID!
should be written as

a = b + c;
d = a + r;

10.5 Miscellaneous Practices

10.5.1 Parentheses
It is generally a good idea to use parentheses liberally in expressions involving mixed operators to avoid operator precedence problems. Even if the operator precedence seems clear to you, it might not be to others-you shouldn’t assume that other programmers know precedence as well as you do.

if (a == b && c == d) // AVOID!
if ((a == b) && (c == d)) // RIGHT

10.5.2 Returning Values
Try to make the structure of your program match the intent. Example:

if (booleanExpression) {
return true;
}
else {
return false;
}
should instead be written as

return booleanExpression;

10.5.3 Expressions before ‘?’ in the Conditional Operator
If an expression containing a binary operator appears before the ? in the ternary ?: operator, it should be parenthesized. Example:

(x >= 0) ? x : -x;

10.5.4 Special Comments
Use XXX in a comment to flag something that is bogus but works. Use FIXME to flag something that is bogus and broken.

// XXX This is not very efficient
return new MyObject();

// FIXME Should return a proper value
return null;


  1. Tools & Jindent

Check out Jindent. It is a ‘code beautifier’ with customizable behavior that really cleans up your code.

It can be found on zloty in the /public/downloads/Java/beautifiers/Jindent/ directory on zloty. There you can also find the properties file Tryllian-Style.jin, that defines most of for the Tryllian code conventions. Put this file in your home directory, install Jindent by putting the Jindet.jar in your classpath and run Jindent by typing:

java Jindent -p Tryllian-Style.jin -f “*.java” -d newFiles

Note: add the -cr option on Windows systems for proper line breaks.

This will format all java files in current directory and save the the formatted versions in the directory newFiles.

Product home page: www.c-lab.de/~jindent


  1. Further reading
    This document only focuses on code lay-out. Other useful resources for writing kosher code are the following

How to Write Doc Comments for Javadoc. Sun’s official guide to writing javadoc comments. Coming up: Tryllian’s javadoc guidelines.

Java in Practice. A very clear and practical book on how to write clean code. Tryllian owns two copies.

Refactoring: Improving the Design of Existing Software. An excellent book on how to modify existing code to make it better. There’s a copy at the Tryllian office.

Software Patterns. The famous book by the ‘Gang of Four’ on generic software patterns.

AntiPatterns. A very good book on how not to write code. Although it is not java-specific and somewhat focusing on managing software projects, it gives a good insight on what not to do. And the names of the anti-patterns are instant classics: Lava Flow, Analysis Paralysis, Boat Anchor.


13. Code example


package com.tryllian.gossip.agent.tasks;

import java.io.; import com.tryllian.agent.;
import com.tryllian.gossip.agent.; import com.tryllian.gossip.global.interfaces.;
import com.tryllian.toolkit.; import com.tryllian.util.;

/**
The LeaveTask takes care of sending the agent to the next stop.
The task takes the next unvisited location from the itinerary and tries
to move there.
The task succeeds when the agent has moved. It fails when the
agent was not able to move.


The itinerary can be found in the AgentKnowledge
@see com.tryllian.toolkit.AgentKnowledge#getItinerary()
@author Hes Siemelink
*/
public class Leave
extends AbstractGossipTask
implements Serializable
{
static LogTopic debug = Log.topic(“Leave Task”);
static LogTopic error = Log.topic(“Leave Task ERROR”);

/** The location where this task is started */
Location initialLocation;


public Leave() {
}


/** Does nothing. */
public void sense() {
}


public void startTask() {

    super.startTask();
    initialLocation = getRoom().getLocation();
}


/**
    We just pick the next stop out of our itinerary if we had them all, we'll
    just have to go home..
 */
public void reason() {

    // Move if we haven't moved yet.
    if (!hasMoved()) {
        moveSomewhere();
    }
    // Complete task if we have moved.
    else {
        succeedTask();
    }

    // Note: if we couldn't move, this task fails in handleFailedMove();
}


/**
    Returns true if the agent is at another location than when we started
    this task.
 */
private boolean hasMoved() {

    debug.println("Comparing initial location: " + initialLocation +
      " with new location: " + getRoom().getLocation());
    debug.println("And returning for hasMoved: " +
      !(initialLocation.equals(getRoom().getLocation())));
    return !(initialLocation.equals(getRoom().getLocation()));
}


/**
    Queue a move action to the next action of the itinerary.
 */
private void moveSomewhere() {

    ActionFactory af = ActionFactory.getInstance();

    // Move to an unvisited location
    try {

        Location nextPlace = getAgentKnowledge().getItinerary().nextLocation();
        debug.println("Off to the next location :" + nextPlace);
        enqueueAction(af.createMoveTo(nextPlace));
    }
    // An exception is thrown if the Itinerary has no more unvisited places
    // Move home in that case.
    catch( IllegalStateException e) {

        debug.println("No more new places in the itinerary; moving home");
        enqueueAction(af.createMoveHome());
    }
}


/**
    If we failed to move, we'll take the next stop in
    the next reasoning phase
    @param e The exception giving additional information
 */
public void handleFailedMove(MoveException e) {

    debug.print("Move failed: " + e);

    // Fail task if there are no moreplaces we can try to go to.
    if (!getAgentKnowledge().getItinerary().hasMoreElements()) {

        failTask();

        //Now make sure we're not going to move again immediatly.
        getKnowledge().setProperty(GossipTask.USER_REQUEST_TO_LEAVE,                                        GossipTask.FALSE);
        getAgentKnowledge().getItinerary().reset();
    }
}

/**
    Throws Refusal, since agent is already trying to leave.
 */
public void requestMove() throws Refusal {

    throw new Refusal("Agent is already trying to leave.");
}

}