Friday, December 17, 2010

Java TimeUnit: More than just a unit of time

My conception of time, my ability to distinguish between consecutiveness and simultaneousness - seemed subtly disordered so that I formed chimerical notions about living in one age and casting one's mind all over etenity for knowledge of past and future ages.

- "The Shadow out of Time", H.P. Lovecraft
Consider the case when you need to call a method that requires you specify a time duration, for example, specifying what the timeout should be for a service making a web call. Usually the time related argument is an int or long, with an inferred unit of measurement (usually milliseconds, but sometime seconds). As you may be thinking of a unit of measurement other than what the method wants, it becomes neccessary to do a conversion. For instance, to specify a timeout of 30 seconds may neccessitate that you actually specify 30000 milliseconds. This conversion is not difficult, but it is tedious (and can cause problems when maintaining code). The good news is that conversion doesn't need to be tedious (and, in some cases, may not be necessary).

Wednesday, December 1, 2010

Unit tests: the fallacy of 100% coverage

"The Hounds of Tindalos!" he muttered. "The can only reach us through angles. We must eliminate all angles from this room. I shall plaster up all of the corners, all of the crevices. We must make this room resemble the interior of a sphere."

- "The Hounds of Tindalos", Frank Belknap Long
I'm an ardent supporter of having unit tests for one's codes, having first hand experienced the benefit they give when you need to refactor code. As a result, one thing that really irks me are programmers who view unit tests as, at best, a necessary evil and therefore try to write as few tests as possible. To them, a suite of tests is good if the tests execute a lot of the code. If these programmers could achieve 100% code coverage, then they would feel their work is done: no more tests need to be written! While this belief might be true for some code, in general it does not hold true: for most classes, simply having 100% code coverage says nothing about whether the code is truly doing what it should do.

Monday, November 22, 2010

Java: Binary Compatibility - more than meets the eye

You were a fool, Joseph Curwen, to fancy that a mere visual identity would be enough. Why didn't you think of the speech and the voice and the handwriting? It hasn't worked, you see, after all.

- "The Case of Charles Dexter Ward", H.P. Lovecraft

Just a quick entry before Thanksgiving, this time concerning binary compatibility for Java.

Most of the time when a method is altered it's easy to spot when a change is not backward compatible with the prior version. After all, if the prior method took a String as its argument and now takes List<String> instead, clearly any client code calling the method will need to be updated. But what happens when you loosen the restrictions, for instance you originally required a HashMap and you want to change the method to require just a Map interface? If you've not encountered this situation before, you may find the answer suprising: your client's code will not run unless they first recompile with your updated code.

Thursday, October 28, 2010

Coherence: One thread is not enough!

You inform me, that no Part must be missing if the finest Effects are to be had, but you can not but know how hard it is to be sure.

- "The Case of Charles Dexter Ward", H.P. Lovecraft
It surprised me no end to find out that the when using a Distributed Cache for Coherence, the default number of daemon threads used to process incoming requests was zero, meaning that all work is performed on the service thread for that cache. This will make a major impact when you are using a cache to handle a large number of concurrent requests. Fortunately, it's not hard to fix this.

Tuesday, September 21, 2010

Coherence: when the key is not the whole key

Yog-Sothoth is the key and guardian of the gate. Past, present, future, all are one in Yog-Sothoth. He knows where the Old Ones broke through of old, and where They shall break through again.
- "The Dunwich Horror", H.P. Lovecraft
Recently at work I was involved in implementing a distributed cache with Coherence to improve performance with a third party web service. Integrating the call to the web service with the cache was not difficult, however I did encounter a twist in that calls to the web service required information which, while tracked by that service, did not in any way affect the result we got back from the service. In other words, only part of the key was needed to correctly retrieve a value from the cache, however all of the key was needed to create the value to add to the cache.

My first thought was that this would be simple to deal with since all Coherence caches are ultimately just extensions of java.util.Map. If we defined the equals and hashCode methods using just the properties relevant to retrieving items from the cache we could have the best of both worlds: the data would be present when needed to call the external web service and the cache would not include redundant entries. However this did not work, and the particulars of why and what I did to fix things are the topics for this post.