Skip to main content

Suporting Hacks and Versions

Posted by jive on November 13, 2005 at 9:14 PM PST

This is Part II of two previous articles! I like to multitask ... and a good designer knows when resuse is possible!

With respect to XML Standards, in Part I we talked about ways of representing XML Standards using Objects, now we take on a hard problem - taking on an update to a standard! The solution is general in nature and will let you take on any changing API, and indeed support multiple versions at the same time.

With respect to the use of Interfaces and Factories, this article serves as a follow up to the use of Factories, and represents the kind of neat stuff you can get away with in a well designed system.

Architecture Astronauts Alert

If you have a low BS tolerence tune out now, if you want a hint at how geotools plans to support the next big thing - that is easy we write it!

It is the next small thing that has me worried - a lot of the services we use are changing on us, and they are changing versions. How are we to write classes that support both cool shiny new stuff (tm) and last years fashions?

And is there a difference between hackers and the spec writers? Does the tail wag the dog?

Here are some specifics that got me thinking:

  • Style Layer Descriptor (SLD) 1.0 and 1.1
  • Filter 1.0 and 1.1

In short our geospatial standards body is reving on us lets see how we can keep up.

FooBar 1.0

To start with lets take a simple example:

interface FooBar {
   boolean isGood( Geometry geom );
}

And we can assume the usual suspects: FooBarFactory and FooBarFactoryFinder.

Lets say some time passes and a new version 2 comes out that has support for morals, morality is given a range of 0-1 (we are comuter scientists after all).

We would like to add the following:

interface FooBar {
   boolean isGood( Geometry geom );

   /** @since version 2. */
   double getMorality();

   /** @since version 2. */
   void setMorality( double moraility );
}

But if we do that we lose something ....

Using Javadocs

If we make the above change we are now dependent on programmers to read the javadocs, and we all know how well that goes. I tend to use geotools as a binary and hope for the best, especially given the source code releases.

Lets look for something better.

Using Interfaces

What I would really like to preserve is Strong Typing so the compiler (not me) can worry about the different versions.

interface FooBar implements FooBarVersion1, FooBarVersion2 {
   boolean isLabelShield();
}

interface FooBarVersion1 {
   boolean isGood( Geometry geom );
}
interface FooBarVersion2 {
   double getMorality();
   void setMorality( double moraility );
}

This approach makes everything explicit, and allows for fun little non standard geotools hacks (like LabelShield above).

We have a number of benifits, code that is really limitied to Version 1 can say so with FooBarVersion1 interfaces. Code that does not care can track the FooBar baseline. Seems like a winner to me ...

Using Factory

So what is my hesitation? Usability lets look at how this plays out, and see what we can do to make it worthwhile...

We can make explicit factories for each version:

interface FooBarVersion1Factory {
   FooBarVersion1 create(); // default implementation

}
interface FooBarVersion2Factory
   FooBarVersion2 create( double morality ); // default implementation w/ custom morals
}

Our default use of Factory should still work:

interface FooBarFactory extends FooBarVersion1Factory, FooBarVersion2Factory {
   FooBar create(); // default implementation
   FooBar create( double morality ); // default implementation w/ custom morals

}

Is it Good?

So we should be able to answer the question - is this a good design idea?

Lets see how we do?

FooBar hacker = FooBarFactoryFinder.create( 0.9 ); // hackers need a bit of flexability
FooBarVersion1 greenshag = FooBarVersion1Finder.create(); // They were going to get it right the first time

FooBarVersion2 black = FooBarVersion2Finder.create( 0.98 ); // They are pretty sure they got it right

Seriously, this can work. It will let me support Filter 1.0 and Filter 1.1, SLD 1.0 and SLD 1.1 and by extention we can make strongly typed interfaces for WFS1.0 and WFS1.1 clients.

I want to balance:

  • end user frustration, making a Filter and not having it work would be annoying
  • developer frustation, having a great idea (by definition non standard) and not getting your patch in would be annoying

By extention our GeoTools interfaces (and implementations) will need to step back from the standards and be bigger then them. For examples of how to do this look at the WebMapServer implementation that Richard Gould put together.