Three years with Java Simon (2)
December 5, 2011 Leave a comment
This is continuation of the previous post where we somehow got to version 1.0 – that was December 2008.
Working on our first version of Java Simon I learned a lot from my colleagues too. While we shared our views all the time on the OSS library we somehow did even better than on our common (resource limited) projects. We also knew that library must be even cleaner and better than some Information System developed once – often without proper support budget. One guy insisted on finals whenever possible (which I’m not fan of) and he also vigorously refactored methods with boolean flags – and I originally disliked this change. In Simon interface we had methods like:
Map<String, String> sample(boolean reset);
Now we have much cleaner two methods instead of using boolean parameter – not to mention that we have Sample object instead of Map used in early versions:
Sample sample(); Sample sampleAndReset();
Not that we don’t have any method with boolean flag – but the most prominent one is rather management one compared to sample methods:
void setState(SimonState state, boolean overrule);
Generally I don’t like using boolean flag parameters because they are hard to read when you see just plain code. If they are replaced with enums (where suitable) readability goes up instantly. If they are split to two methods – especially when one of them is rather default (like the sample without reset) – even better.
Working on an OSS library (or any other library – even a private one) you have to think way harder (or rethink more often) how to organize your interface, packages and all. I personally hate backward compatibility as an ultimate decision and we knew that we will change the interface here and there. If you want to upgrade then just go through your code and change those few things you have to change! Or don’t upgrade. (I’ll not go on about the whole myth of compatiblity and how often it is not completely true.)
That’s why we decided to release version 1.0 quite soon (December 2008, we started the project in August 2008) and find out what is missing. Version 2.0 followed quite quickly – in January 2009 we had the first alpha (quite stable though) and we decided to focus solely on this without any support for 1.0. The reason was that the Stopwatch behaviour changed quite a lot – for the better.
In 1.0 HalloWorld looked something like this:
SimonStopwatch stopwatch = SimonFactory.getStopwatch("org.javasimon.HelloWorld-stopwatch"); stopwatch.start(); System.out.println("Hello world, " + stopwatch); stopwatch.stop(); System.out.println("Result: " + stopwatch);
Most important feature was that both start and stop were called on the Stopwatch. Now you may wonder what would happen if you started stopwatch twice and stopped it twice as well. It depended… though – honestly – I don’t remember exactly. Stopwatch had thread-local variable that remembered start timestamp (nanoseconds of course) and stop was expected to be called in the same thread. Double start and stop was illegal operation. Now this implied two serious limitations. The first was potential memory leak on the thread-local variable if you (client programmer) failed (or forgot) to stop the stopwatch. The second was that you couldn’t stop the stopwatch in a different thread.
This was troublesome design and happened to be resolved soon after 1.0 release. Our new HelloWorld looked (and still looks) like this:
Stopwatch stopwatch = SimonManager.getStopwatch("org.javasimon.examples.HelloWorld-stopwatch"); Split split = stopwatch.start(); System.out.println("Hello world, " + stopwatch); split.stop(); System.out.println("Result: " + stopwatch);
Now the client programmer is fully responsible for working with the Split, there is no thread-local and the worst thing that may happen to the stopwatch is that its “actual” count will go up and up (and so indicate some problem with missing stops). Split will be garbage collected – unless stored by the programmer (his fault anyway ;-)).
Another important features coming with 2.0 were JMX support (MX Bean) and Callbacks – these allowed programmer to hook on various events. But more about these in my next post, right?