development / guidelines
 
 
-- FILE ---------------------------------------------------------------------
-- name       : DevGuideLines.txt
-- project    : BoarderZone: Development Environment
-- created    : Leon Poyyayil - 2001-01-26
-- language   : English
-- environment: the human readers mind ... ;-)
-- copyright  : (c) 1990-2024 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 ----------------------------------------------------------------------