Difference between revisions of "Style Guide"

(geWorkbench Developer Style Guide)
(geWorkbench Developer Style Guide)
Line 6: Line 6:
 
* If a local variable is adequate to serve your purpose, do not make it a member variable.
 
* If a local variable is adequate to serve your purpose, do not make it a member variable.
 
* If a private member serves your purpose, do not make it public or default or protected.
 
* If a private member serves your purpose, do not make it public or default or protected.
* If the class is intended to be extended, declare it as final - unless those require by geWorkbench framework not to be final.
+
* If the class is not intended to be extended, declare it as final - unless those require by geWorkbench framework not to be final.
 
* If the method parameter is intended to be read only, declare it as final.
 
* If the method parameter is intended to be read only, declare it as final.
 
* Name classes, variables, and methods what they really are or really do. If you cannot name your class as a noun, something is wrong with your design; if you cannot name your method as a verb, something is wrong with your design.
 
* Name classes, variables, and methods what they really are or really do. If you cannot name your class as a noun, something is wrong with your design; if you cannot name your method as a verb, something is wrong with your design.

Revision as of 08:57, 28 October 2011

geWorkbench Developer Style Guide

This document provides a style guide for developers of geWorkbench. The old content that has not been updated since 2005 may include something useful, so I keep them for now at the end the page, titled "Old Content".

There are various good style guides out there on the Internet, this document is meant to focus on the issues that are more relevant to the current code base and development activity of geWorkbench. While it is not practical to enforce the style over the legacy code, new development should follow the guide line described here. Any comments are very welcome.

  • Remove dead code. This includes: unused local variables, unused private members, unused public members, out-of-date comments, unused classes/files, unless you have specific reason to expect to use it soon or as part of unfinished development.
  • If a local variable is adequate to serve your purpose, do not make it a member variable.
  • If a private member serves your purpose, do not make it public or default or protected.
  • If the class is not intended to be extended, declare it as final - unless those require by geWorkbench framework not to be final.
  • If the method parameter is intended to be read only, declare it as final.
  • Name classes, variables, and methods what they really are or really do. If you cannot name your class as a noun, something is wrong with your design; if you cannot name your method as a verb, something is wrong with your design.
  • If one java file is over 1000 lines, the design deserves very careful scrutiny.
  • If class A refers to class B, and at the same time class B refers class A, the design needs scrutiny.
  • Refer to the object by a proper interface instead of implementation class when possible.

geWorkbench Code Organization Standard

Old Content

Project Structure

This section describes the directory structure of the project. The root directory structure contains the JBuilder and IDEA project and library files. It also contains this file, the java.policy file, and the build.xml ant build file.

  • _all - A folder for a placeholder module required for the IDEA IDE.
  • annotation - Marker annotations for various chip types.
  • components - The top-level directory for geWorkbench components.
  • data - Sample data files for the project.
  • lib - Library files for core geWorkbench.
  • plugins - Plugins for the Cytoscape package.
  • src - Source code for core geWorkbench.

Each component is in a subdirectory of the components directory. It contains an IDEA .iml module file and it's directory structure is as follows:

  • lib - Library files depended on by this component.
  • src - Source code for the component.

Note that the components can depend on the core classes (those defined in ./src) and the core libraries (those defined in ./lib). However, components cannot depend on each other, and the core classes cannot depend on components.

Creating a New Component

A new component should be added as a new subdirectory of components. The subdirectory should be given a simple, descriptive, lower-case name. It should contain src and lib directories. Most importantly, the component must not depend on the classes or libraries of any other component, nor should another component depend on it. Also, the core geWorkbench classes should not depend on its classes or libraries. The build.xml will enforce this, as will the IDEA project. However, the JBuilder project currently does not enforce this constraint, so be careful when using JBuilder.

Coding Style

The coding standards outlined by Sun are observed. Here are the coding standards that are particularly important to us:

Capitalization

Constants must be in all-capitals, with underscores between words:

public static final int MAXIMUM_FILES = 100;

No other identifiers may contain underscores but constants. Class, interface, enum and annotation names must be capitalized, with all subsequent words also capitalized:

public class SampleClass extends AnotherSampleClass {

Variable and member names must have their first letter lower-case, and subsequent words capitalized:

private String fieldName;
private abstract void processFile(File file);

Some developers differentiate between method variables and class members by prepending m_ or just _ to member names. This is not a standard practice, so is not observed. Identifiers in property files are all lower-case with periods separating words:

maximum.files=100

Type wildcards in generics must be a single capital letter:

public interface Generic<T, S extends Serializable> {

Annotations

Annotations can either appear on the same line as their associated declaration, or on the line before it:

@Subscribe public void receive(Integer value) {

@Script(dependencies = {STATE_UNINITIALIZED, STATE_COMPLETE}, result = STATE_INITIALIZED)
public void initialize() {

Variable Naming

Variables should be given verbose names, even if they are only used in relatively small code blocks. Using the auto-complete functionality of modern IDEs makes compliance with this rule painless. Exceptions are simple index variables, such as those introduced in for(;;) statements:

for (int i = 0; i < 100; i++) {

Braces

All if, while and similar block structures must be surrounded by braces, even if the body of the block consists of only one statement:

if (index < 100) {
    System.out.println("index= " + index);
}

No Shortcuts

Java provides some C-style shortcuts, such as the ++, += and ?: operators. The ++, += operators can be used by themselves (for example, ++ is often used in a for statement) but they should not be included in other statements. The ?: operator should only be used very sparingly, usually in statements that construct strings. Here is an example of a bad use of ++:

while (i < 100) {
  System.out.println("i= " + i++);
}

This is preferred:

while (i < 100) {
    System.out.println("i= " + i);
    i++;
}

This is an acceptable use of ?::

boolean available;
...
System.out.println("The file is " + (available ? "available" : "unavailable") + ".");

However, it is a safe bet to never use ?:.

Tabs

A tab-width of 4 should be used.

Code Documentation

Code must be documented using the Javadoc standard. All classes, interfaces, enums and annotations must have an introductory Javadoc explaining its purpose. All public methods must also have explanatory Javadocs. Methods that perform non-trivial operations should have normal comments (not Javadoc) that explain the code. Such comments should precede the line (or lines) of code that they describe. For example:

/**
 * Shuts down the componentRegistry (and terminates any pending aysnchronous dispatches).
 */
public void shutdown() {
    // Iterate through all active synch models
    Collection<SynchModel> models = synchModels.values();
    for (SynchModel synchModel : models) {
        // Shut down the synch model
        synchModel.shutdown();
    }
}

Packages

Package names should follow the inverse-domain rule. If the domain of your organization is

subdomain.domain.tld, then the package structure should be rooted at tld.domain.subdomain.

Capital letters or underscore characters should never appear in package names.

Otherwise, the organization of packages is left up to the developer.