abstract

This document describes the tools and methods used to keep the java sourcecode of the WebScarab project clean, well-formed and functional. As for now it is a draft and still needs to be reviewed, extended and approved.

tools / libraries

purpose name revision download location
building projects ant 1.4.1 http://jakarta.apache.org/builds/jakarta-ant/release/v1.4.1/src/jakarta-ant-1.4.1-src.tar.gz
testing code junit 3.7 http://download.sourceforge.net/junit/junit3.7.zip

writing code

If some piece of code requires technical specifications of any kind, the tech spec must be written and approved by the developer team BEFORE the implementation process begins.
If it shows up, that some interface must be changed, this has to be announced. Again, the tech specs have to be rewritten first, after approval interfaces may be changed.
To assure that any piece of code is working exactly as one expects, junit tests are used.
The general contract is to write tests first, i.e. once you defined some interface ("interface" means members, methods and ctors of any class that have public scope) you should define it's behaviour by writing explicit tests for it.
Example
class Foo {
  int _x;
  public Foo () {}
  public int get() { }
  public Object doSomething( Object val ) {}
}

Now let us assume you want the following behaviour: You would write junit tests like this:
void testInit () {
  Foo f = new Foo();
  assertEquals( 2, f.get() );
}

void testDoNotNull () {
  Foo f = new Foo();
  assertNotNull(  f.doSomething( null ) );
}

void testDoInc () {
  Foo f = new Foo();
  f.doSomething( "val" );
  assertEquals( 3, f.get() );
  f.doSomething( "val" );
  assertEquals( 4, f.get() );
}
Now AFTER having defined the behaviour of the interface you implement it:
class Foo {
  int _x;
  public Foo () { _x = 2; }
  public int get() { return _x; }
  public Object doSomething( Object val ) { return null == val ? "null" : val; }
}

Everything alright?
NO!
Surely you noticed that the last test will fail, since _x is not incremented on doSomething().
By writing the test first you will discover immediately that something goes wrong.
If you do it this way around it is more likely that you do not forget to test for a behaviour that you want to have.

requirements for "stable" branches / releases

Until the first major release, no backwards compatibility for obsolete interfaces will be provided.
After the first major stable release, old interfaces have to be maintained exactly for the next following minor release.
Old interfaces have to be marked as deprecated and MUST BE REMOVED AND SUBSTITUTED COMPLETELY with the next minor release.
Only sourcecode that fulfils the following requirements will be allowed to be published in "stable" releases or to be commited in "stable" CVS branches: The last point is some assurance for the case that a developer who wrote some awfully efficient, but yet cryptic code suddenly disappears.
If every class (sourcefile) is at least known and understood by two active developers, one can be sure that every part of the whole system can be maintained by somebody.

source code format

packaging

These are the rules for package naming: Every package may depend on ...util.
All interfaces used to exchange data between the main packages must be declared in the main packages and NOT in any subpackages.