In order to facilitate a large group of people working on this codebase we will
need to enforce a set of coding standards. So when submitting code for Xj3D
we ask that you follow these conventions. These standards are in place in order
to keep the code maintainable. There's half a million lines of code in the
core toolkit and thousands of users. The codebase is now over 7 years old. These
standards are to ensure that we can continue to have a long-term maintainable
codebase and not follow the fad de jour of Java.
The golden rule is to develop this code for others, not yourself. Nobody owns
any particular piece of code. No-one does. Anyone can edit any part of the
codebase. Follow and copy the footsteps of those that have gone before you.
Formatting
- Only one Class/Interface per file (inner classes excluded)
- Use 4 spaces for indention. Convert tabs to spaces
- No line should exceed 80 chars in length
- Clarity rules. We don't care whether you can fit more lines per
page by condensing all spaces and removing blank lines. Non-readable
code is non-readable code. Keep it well spaced.
- Comments in line where necessary to describe possible bug
conditions, gnarly bits of non-obvious code etc.
- K & R-style bracketing and indenting.
File Structure
-
The macro structure of each file shall be.
- Copyright statement
- Package statement
- Imports
- Class javadoc (including @version and @author tags)
- Class code
- All package imports should be enumerated till 4. Then use the *
wildcard.
- List standard imports for packages that need to come from external
sources, such as the JDK and JARs in the lib directory in a separate
commented section to those that are internal to this codebase.
It is recommended that all wildcarded groups are declared first, and
then individual classes separate. This allows for individual classes
to override a potentially same name class in a different, wildcarded
package.
For example:
// External imports
import java.util.*;
import java.awt.Image;
import org.j3d.utils.HashMap;
// Local imports
import org.web3d.vrml.nodes.VRMLNormalNodeType;
- Our general class structure is:
- static constants
- static variables
- class variables (if a node implementation then it is fields
representations followed by general working vars)
- static constructor block, if needed
- Constructors
- Interface implementations
- Internal class methods working from public through to private
There's no specific order within a class for which interface is defined
where, but typically we will put the most derived first and work out way
to the least derived.
- Put all methods implementing an interface or overriding a base class
together and label. For example
//-------------------------------------------------------------
// Methods defined by VRMLColorNodeType
//-------------------------------------------------------------
/**
* Set a new value for the color field.
*
* @param newColor An array of 3 floats(r,g,b) specifying the new color
* @throws ArrayIndexOutofBoundsException The array had less then 3 elements
*/
public void setColor(float[] newColor) {
...
}
- Use of inner classes is highly discouraged. There are good times to
use them, but using annonymous adapters every second line of code will result
in the class being rejected for submission. Expect to be put through a grilling
and be able to justify their existance if you submit code that has them in.
-
Circular dependencies are not acceptable. A class shall not depend on
itself through a circular dependency loop. Use traditional refactoring to
break this cycle. Also, our make system will enforce this somewhat through a
structured build of the system in a linear dependency order.
- Constants, particularly for Strings should be used wherever possible. At some
point in the future, when we internationalise the error reporting, we'll come
through and strip the strings out, placing them in an external file. By having
all of them in the top of the class as constants, this will make our life an
awful lot easier down the track.
- Access modifiers were provided for a reason. Use them. Leaving every variable
in a class with the default package-protected access is not acceptable. If
there is a need for package-protected access to another field, reconsider
the design. It's almost guaranteed you've done something wrong.
Naming Conventions
Generally follow Java API naming conventions. Be descriptive, not terse. The name
should reflect its use.
Specific conventions we use internally for interfaces:
VRML* An interface describing the abstract capabilities of a
class of nodes. Mostly this corresponds to the X3D abstract node type
definitions, but we do break from that when required to extra internal
capabilities.
- Node implementation uses
BaseNodeName for the common
renderer-implementation field handling. Found in the
...renderer.common.nodes set of packages. Renderer-specific
nodes use RendererPrefixNodeName - eg
OGLNormal. These are found in the renderer-specific packages.
- Anything that is specific to a particular renderer prepends the renderer
type name to the class name. eg J3DUserInputHandler.
- Variables that hold the value of a VRML/X3D field of a node are defined as
with
vfFieldName. When the field is an SFNode, and thus
there's the possiblity of a PROTO version, then the proto is declared as
protected VRMLProtoInstance pFieldName.
There are more than this. Check each of the section-specific documents
for further details.
Commenting
It's the law in this country!
Code without comments is typically rewritten as no-one knows
what it does. Code submission without comments will be rejected. Overly
verbose commenting is preferred over simple three word summaries.
We use JavaDoc to generate documentation so please use its conventions. All
class variables should have a descriptive comment. Methods should define
their behavior, document their parameters and what exceptions can be generated.
In general, we expect that a method declaration should include a simple summary
and then description of any significant pre and post conditions, or expectations
of the given parameters. ie, if a null value is passed in for an array reference,
will this cause a crash, NPE or explicitly used to clear the value?
JDK and external libraries
Xj3D has to run on a very wide number of platforms. Expect that we will require
code to run on the previous generation to the current JDK version. Right now,
that means we require code (and thus libraries used) to be able to run on a
JDK 1.4-class JVM and JRE set of libraries.