-- FILE ---------------------------------------------------------------------
-- name : DevGuideLines.txt
-- project : BoarderZone: Development Environment
-- created : Leon Poyyayil - 2001-01-26
-- language : English
-- environment: the human readers mind ... ;-)
-- copyright : (c) 1990-2025 by Leon Poyyayil (private), Switzerland
-- license : this is free software licensed under the GPL. see COPYING
-----------------------------------------------------------------------------
Table of Contents line
----------------- ----
1. Executive Summary ..................................................... 24
2. Organizational Issues ................................................. 35
3. Naming Conventions .................................................... 55
4. Coding ............................................................... 110
5. Style ................................................................ 163
A. References ........................................................... 325
B. Revision History ..................................................... 332
C. Authors contact info ................................................. 346
1. Executive Summary
--------------------
This document intends to provide a basis to coordinate the software
development process for the BoarderZone.net namespace.
It covers the most basic issues to ensure the code developed by different
people can be viewed, understood and enhanced by others. For this to work
it is necessary that everybody sticks to some common rules which are
outlined herein.
2. Organizational Issues
------------------------
- Documentation has to be kept in non-binary formats only.
=> usage of .txt, .htm, .xml, .rtf, ...
Advantages:
- independent of (possibly platform dependent) tools
- can be 'grepped' through ...
- can be compared with standard diff tools
- Test programs go into a sub-package named "test" of the
package of the module to be tested.
- All identifiers, comments and documentation are to be kept
in English
=> least common denominator of languages in IT
(more folks are comfortable with English than with German)
=> supports a fluid reading of the code without necessity
to switch between languages (keywords are English anyway)
3. Naming Conventions
---------------------
- Generally: according to the Java guidelines, see [FLAN]
in short:
- packages: lowercase names (e.g. "net.boarderzone.util")
- classes: mixed case style, starting with a capital letter
(e.g. "SuperDuperTool")
- interfaces: same as for classes, but DON'T start with the
letter 'I' to distinguish them (e.g. "IClientHandler").
instead the implementing classes should append an "Impl"
to their name.
this encourages working with the interfaces instead of the
implementations ...
- methods/variables: mixed case style, starting with a lower
case letter (e.g. "getMemberValue()" )
- use self describing names rather than cryptic abreviations.
the typing overhead for writing the code is worth the better
readability!
- Avoid underscores in identifiers (for better 'typeability')
- If an identifier contains a commonly used abbreviation, don't
write it in all capital letters (e.g. "MyHTTPHandler") but
rather capitalize it as a normal word, e.g. MyHttpHandler.
This increases readability.
- Give all variable names a one- or two-letter lower case prefix
to prevent confusion between variables of different scopes etc:
- 1. scope prefix:
- 'c' for class statics
- 'm' for class members
- 'l' for method locals
- 'p' for method parameters
- 2. type prefix:
- 'n' for numeric values of base types
- 'b' for boolean values
- constants are to be kept in all uppercase letters
Examples:
- a global numeric constant:
public static final int MY_ID = 12345;
- a value accessible to all class instances:
private static boolean cbInitialized = false;
- a member instance of some object
private SomeClass mOutputFrame;
- an instance method of some class:
private void myFunc(
final int pnValueToSet // this is a comment for this parameter
)
{
final int lnFactor = 10; // a local constant
mnValue = pnValueToSet * lnFactor; // set the member ...
} // myFunc
4. Coding
---------
- All code has to be located under the package net.boarderzone
- All data members are private, access exclusively via methods
=> do not declare public or protected data members!
=> makes sure the state of an object can not be rendered
inconsistent by some extern code.
The only exception to this are package protected members which
allow direct access to the sibling classes in the same package.
This is allowed because normally within a package the classes
are written to cooperate closely and hence the author has
complete control because no classes will be added by others.
However, this should only be used if really necessary or if
it allows significant simplification.
- Order of methods in the file: first constructors, then other
methods grouped according to functionality. Don't artificially
separate methods which functionally belong together just because
of different access levels (public/protected/private).
- Avoid returning mutable class instances of members (java strings
are immutable) because these objects can then be modified from
outside, what breaks the desired encapsulation!
Exceptions can be made from this rule if the returned class ensures
its proper state and all possible mutations will not render the
owning class instance invalid.
- If returning class instances is necessary and its proper state
cannot be enforced, then do it by returning a (deep) copy of the
object instead of the actual member
=> this is a performance loss, but currently the only way to pre-
vent breaking the encapsulation ... :-(
This might be changed in the future, when java (finally) supports
the 'const' keyword (currently only reserved).
- Define a copy constructor and a copy method for classes with data
members whenever possible (when doing this, implementing the
Duplicatable interface isn't much more work, so do it ...)
=> provides for easy deep-copying of an object when returning it
from an accessor method
=> the additional (covariant) duplicate() method has the advantage
of returning an object of the correct type, so no casting is
necessary under certain circumstances
- Initialize all variables of base types explicitly (for readability)
if the default value is different from the java standard default
value.
- Mark all method parameters as final to prevent their accidential
modification in the method body.
5. Style
--------
- No use of the TAB character, do all indenting with spaces
=> prevents code layout problems when working with different
editors that have different settings for the tab width (code
that looks nicely arranged for a tab width of 8 may look pretty
unreadable in an editor that uses a tab width of 4)
- Use a consistent 'tab' (indentation) width of 2
=> enough for good readability without extending the code width too
much for deeply nested sections
- Keep the maximum line length below 100 chars
=> less problems when printing the source code (otherwise ugly
wrapping occurs or the end of the line is not visible ...)
- Prevent trailing spaces at the end of lines
- Prevent trailing empty lines after the end-of-file line
- Usage of CR/LF for line breaks throughout all files
=> this is 'on the safe side' when looking at the code on a
platform with a different end of line marker, because the
lines are still distinct.
When viewing a file with a LF line break on a system with
CR/LF or LF/CR end of line marker, it appears as a single
_very_ long line ...
Exceptions to this rule are only allowed if a file doesn't work
with the CR/LF line ending (e.g. unix shell scripts).
- Every statement has its own line in the file
=> easier debugging (step through, stack trace line numbers, etc)
example:
if ( lSomeClass.doSomething() ) lSomeClass.doSomethingElse();
when stepping through the line above it's not intuitively clear
which statement will be executed next ...
- Avoid changing the values of non-final method parameters to prevent
influencing the calling code (treat them as constant objects).
- Always terminate case statements with a break (don't use the "fall
through" possibility for better encapsulation of the different cases).
Only don't do this if it would result in unreachable code (e.g. after
a return or throw statement).
- Try to avoid the continue statement (don't write "spaghetti code")
- Provide only one return statement in a method (see above ...)
=> otherwise cleanup code has to be kept in multiple places
(e.g. closing network connections etc.)
- if, else, while and do statements shall be followed by a block in
braces, even if it has only a single statement or is empty
=> prevent the (surprisingly rather common) error of changing the
program flow when commenting out a single line ...
- Dates should be kept in the format yyyy.mm.dd (especially for
file names and log entries) for correct sorting.
Sorting files according to their file system timestamp will not
yield the desired results when the files have been modified ...
- _each_ file has a file header of the following (general) form:
// -- FILE ------------------------------------------------------------------
// name : <filename>
// project : <project>
// created : <author> - <date>
// language : <java|shellscript|...>
// environment: <JDK 1.3.0|bash|...>
// copyright : <copyright notice>
// license : <license type & reference>
// --------------------------------------------------------------------------
Of course the comment characters have to be adapted to the various
file formats (xml, sql, java, ...) but the information of each line
should always be present.
- _each_ file ends with an end-of-file delimiter line and an empty line
- _each_ class/interface has a header of the following form:
// -- CLASS -----------------------------------------------------------------
/** This is a short description of the class.
Some more explanation on the usage/behavior of the class.
@author <author>
@version <version>
@since <version>
*///-------------------------------------------------------------------------
- _each_ method has a header of the following form:
// -- METHOD ----------------------------------------------------------------
/** Overloaded version of this method.
outputs a simple string to state where we are ...
@since <version>
@param pText the text specifying where we've been called from
@return state of completion: true if all is ok
*///-------------------------------------------------------------------------
more tags can be added if necessary/desired, but the @since tag should
always be present
- avoid multi-line comments (except for the javadoc class/method headers)
=> better possibility to temporarily disable a lot of code
=> no problems with nesting such comments (the first closing tag closes
all opening comment tags ...)
- repeat the method name as comment on the terminating line of the method
=> clear which method ends even when only looking at the last lines
=> especially helpful when a printout of a method spans a page break ...
Example:
public void myFunc()
{
// do something here
} // myFunc
- indentation according to the following examples:
private boolean myFunc(
final int pnValueToSet, // the value as read from the file
final int pnFactor // the factor to scale the value with
) throws Exception
{
boolean lbValueSet = false;
int lnFactor = pnFactor; // create a local copy we can modify
if ( lnFactor < 0 ) {
throw new Exception( "invalid factor: below zero" );
} else if ( lnFactor == 0 ) {
throw new Exception( "invalid factor: is zero" );
}
for ( int lnI = 0; lnI < lnFactor; lnI++ ) {
// do something here
}
while ( lnI > 0 ) {
// do something else here
}
do {
// yet something else
} while ( lnI < 0 );
switch ( lnI ) {
case 0:
// something here
break;
case 1:
// something else here
break;
default:
// yet something different here
break;
}
mnValue = pnValueToSet * pnFactor; // set the member ...
lbValueSet = true;
if ( mnValue > 0 &&
pnFactor < 2000 &&
( lbValueSet || mnValue == 0 ) ) {
// nothing to do here with this weird condition ...
}
return lbValueSet;
} // myFunc
A. References
-------------
[FLAN] - Flanagan, David
Java In A Nutshell, ISBN 1-56592-487-8
Chapter 7 - Java Programming and Documentation Conventions
B. Revision History
-------------------
2001-01-26 - lep - created
2001-02-12 - lep - pre-release for public comment ...
2001-11-14 - lep - changed prefix for variables in naming conventions
2002-01-28 - lep - changed naming convention for interfaces
2004-04-22 - lep - adapted to current style & requirements
2004-06-19 - lep - changed to require final keyword where appropriate
2004-06-19 - lep - changed table of contents to point to line numbers
2004-08-16 - lep - fixed some minor typos and added some clarifications
2007-09-20 - lep - updated to reflect new style and findings
2023-10-17 - lep - minor formatting changes
C. Authors contact info
-----------------------
Leon Poyyayil (lep) : leon.poyyayil@boarderzone.net
-- EOF ----------------------------------------------------------------------