Coding Conventions

For the most part, LimeWire uses the coding conventions recommended by Sun. However, the rule of thumb is to use the existing convention when you are modifying a class (consistency within a file is most important).

Here are a few additional pointers:

  • Don't use Hungarian notation.
  • Put members at the top of classes (static members above non-static members), methods below constructors and inner classes at the bottom.
  • Reserve capital names for private static final constant variables. For example, 'private static final long THREE_DAYS = 3 * 24 * 60 * 60 * 1000;'
  • Use underscores to separate all capitals words, but don't use as a prefix for a private or protected class variable.
  • Don't put in a space between the method name and the parenthesis.
  • Break up long methods into smaller ones.

In general, catch only what would be a network-level error.

  • Don't catch 'Exception'; programming errors should propagate.
  • Use an exception instead of returning null to indicate an error.

All messages to the user must be translate-able and you should avoid System.out, System.err or printStackTrace, but use debug logging instead.

  • When debugging, use the LOG.debug method (create the LOG instance via 'private static final Log LOG = LogFactory.getLog(MyClass.class);'.
  • Prefix log statements that concatenate new strings with 'if (LOG.isXXXEnabled()){...}'. Otherwise even with logging turned off, you end up creating strings that get discarded.

Format

You can view the LimeWire format conventions in Eclipse via Project > Properties > Java Code Style > Formatter.

In summary, LimeWire uses 4 spaces indents and avoids whitespace or brace changes unless there was a very good reason (it makes it difficult to track code changes with CVS). Also, the LimeWire code uses K&R style of indentation, as illustrated:

public class Foo {
    public static String getEncodedString(byte[] bytes, String encoding) {
        try {
            return new String(bytes, encoding);
        } catch (UnsupportedEncodingException impossible) {
            throw new RuntimeException(impossible);
        }
    }
}

Comments

In general, LimeWire follows Sun's Javadoc conventions, but diverges on a few points. Most notably, LimeWire development doesn't require every parameter and return value have an '@param' and '@return' tag (it's not appropriate for all contexts). Also, LimeWire doesn't use the '@author' tags; you can use CVS to get that information. However you should use javadoc comments for all important methods and fields. Additionally follow these guidelines:

  • Remove dead commented code.
  • Don't javadoc inside methods, instead use //.
  • Mark comments about future work with 'TODO' to see in Eclipse's task view. Also, if code is a workaround of a bug, list the bug in the TODO so it can be removed when fixed.
  • Keep comments under 80 characters per line.

Because LimeWire uses many threads, you should document all synchronization carefully. This is especially important when using fine-grained synchronization. For example:

/**
 * The number of times we've run the method.
 * LOCKING: obtain counterLock
 */
private int counter;
/** The lock for counter */
private final Object counterLock = new Object();
 
/** Increments the counter. */
void increment() {
    synchronized (counterLock) {
        counter++;
    }
}

Please also document any invariants carefully. This can greatly help people understand your code. The following code example uses mathematical set notation to document that a variable is equal to the number of negative values in an array:

/** The list of numbers we've seen. */
int[] values;
/** The number of negative numbers we've seen.
  * INVARIANT: negatives==| {i | values[i]<0} | 
  */
int negatives;

Tests

When you create a test class, name it with the feature and append 'Test' (You can't have helper test classes that end 'Test' because the test suite will think it's a test and will run it.). Furthermore, prefix 'test' to all methods you want the test suite to call. If the test is a component test, extend from BaseTestCase, but if it's in the limewire/test hierarchy, extend from LimeTestCase.

See our primer on Test Cases for more information.