Feeds:
Posts
Comments

Enums are Brittle

We all know Integer constants are brittle

Consider this example from StackOverflow today:-

Calendar date = Calendar.getInstance();
date.set(2010, 03, 7);
if(date.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
        System.out.println("OK");

The questioner mistakenly thought that the java.util.Calendar set(int year, int month, int date) method followed a sensible human format for representing dates, but in fact the API makes use of zero based int constants to represent the month. The questioner was encouraged to avoid this pitfall by changing his code to date.set(2010, Calendar.MARCH, 7). This of course is better, but the root of the problem lies with the poorly designed Calendar API.

If java.util.Calendar class has been written post Java 5 then the set method could have been defined as set(int year, Month month, int date) where Month is an enum type:-

public eum Month {
JANUARY,
FEBRUARY,
MARCH,
...
}

This would prevent any ambiguity over whether the month parameter is zero or one based.

To change and to change for the better are two different things.

Enums may be preferable to int constants, but they are not as flexible as regular Java classes. You may well find that when you come to modify an enum which was written months ago, you need to refactor the whole thing into a regular class. This of course is time-consuming and you would have been better off designing a class from the start.

Below is an example enum representing a 2D direction on a grid. Direction takes two parameters, deltaX and deltaY which represent the offset of moving in that direction. Given that co-ordinate (0, 0) on the grid is located in the top left hand corner, moving NORTH will result in a negative change in deltaY, EAST will result in a positive change in deltaX and so forth.

enum Direction {
	NORTH(0, -1), NORTH_EAST(1, -1), EAST(1, 0), 
        SOUTH_EAST(1, 1), SOUTH(0, 1), SOUTH_WEST(-1, 1), 
        WEST(-1, 0), NORTH_WEST(-1, -1);
	private int deltaX;
	private int deltaY;
	Direction(int deltaX, int deltaY) {
		this.deltaX = deltaX;
		this.deltaY = deltaY;
	}
	public int deltaX() {
		return deltaX;
	}
	public int deltaY() {
		return deltaY;
	}
}

Direction feels like it should be an enum, as we only have eight possible directions to move in, allowing for diagonal moves. Furthermore this example demonstrates another advantage enums have over int constants – enums support methods. In fact, this enum almost appears to be a regular class, besides the enum declarations at the top.

We encounter a problem with enums when we want to add a method that returns the opposite direction. i.e. the opposite of NORTH is SOUTH, NORTH_WEST is SOUTH_EAST and so on. Here is the first technique.

enum Direction {
	NORTH(0, -1), NORTH_EAST(1, -1), EAST(1, 0), 
        SOUTH_EAST(1, 1), SOUTH(0, 1), SOUTH_WEST(-1, 1),
	WEST(-1, 0), NORTH_WEST(-1, -1);
	private int deltaX;
	private int deltaY;
	Direction(int deltaX, int deltaY) {
		this.deltaX = deltaX;
		this.deltaY = deltaY;
	}
	public int deltaX() {
		return deltaX;
	}
	public int deltaY() {
		return deltaY;
	}
	public Direction getOpposite() {
		return new Direction(-deltaX, -deltaY);
	}
}

By simply negating the deltaX and deltaY values we get the opposite direction right? It doesn’t compile because we can’t invoke enum constructors directly, even from within the enum itself! Let’s try it another way: –

enum Direction {
	NORTH(0, -1, SOUTH), NORTH_EAST(1, -1, SOUTH_WEST), 
        EAST(1, 0, WEST), SOUTH_EAST(1, 1, NORTH_WEST),
	SOUTH(0, 1, NORTH), SOUTH_WEST(-1, 1, NORTH_EAST), 
        WEST(-1, 0, EAST), NORTH_WEST(-1, -1, SOUTH_EAST);
	private int deltaX;
	private int deltaY;
	private Direction opposite;
	Direction(int deltaX, int deltaY, Direction opposite) {
		this.deltaX = deltaX;
		this.deltaY = deltaY;
		this.opposite = opposite;
	}
	public int deltaX() {
		return deltaX;
	}
	public int deltaY() {
		return deltaY;
	}
	public Direction getOpposite() {
		return opposite;
	}
}

In the second technique we have hard-coded the opposite directions, passing them into the constructor. This doesn’t compiler either because you cannot refer to types before they are defined. e.g. SOUTH cannot be referenced in NORTH‘s constructor.

Finally we give up trying to find a work around with an enum and change the whole thing to be a regular class.

public class Direction {
	public static final Direction NORTH = 
        new Direction(0, -1);
	public static final Direction NORTH_EAST = 
        new Direction(1, -1);
	public static final Direction EAST = 
        new Direction(1, 0);
	public static final Direction SOUTH_EAST = 
        new Direction(1, 11);
	public static final Direction SOUTH = 
        new Direction(0, 1);
	public static final Direction SOUTH_WEST = 
        new Direction(-1, 1);
	public static final Direction WEST = 
        new Direction(-1, 0);
	public static final Direction NORTH_NORTH = 
        new Direction(-1, -1);
	private int deltaX;
	private int deltaY;
	private Direction(int deltaX, int deltaY) {
		this.deltaX = deltaX;
		this.deltaY = deltaY;
	}
	public int deltaX() {
		return deltaX;
	}
	public int deltaY() {
		return deltaY;
	}
	public Direction getOpposite() {
		return new Direction(-deltaX, -deltaY);
	}
}

The private constructor ensures that we cannot create any instances outside of the class. The eight public instances and the getOpposite() method provide the only means of access. Note that in this class we can write the getOpposite() method using the first technique.

In conclusion, enums may be an improvement over int constants, but are definitely less flexible than a regular class. If you do decide to create an enum, consider that it may outgrow itself, like Direction did. Creating a regular class from the start may be the better option. In some cases a class may be more verbose than an enum, but then Java is pretty verbose language anyway!

Since I started my new job as a Java Software Engineer, I’ve been doing some training in the form of reading Effective Java by Joshua Bloch. Today I came across the rather baffling method signature below: –

Public static <T extends Comparable<? Super T>> T max(List<? Extends T> list)

“OMG… What is that all about?” I thought at first glance. The description informs me that the method max takes a list of any comparable type and returns the object with the maximum value as defined by the implementation of the Comparable interface’s compareTo method.

So what’s with all the bloat? The answer is that generics are invariant rather than covariant in Java. For example List<String> is not a subclass of List<Object>. In order to make your generic methods as flexible as possible it is necessary to support the inheritance of parameter types, which can cause quite a headache. I think I’ve just about got my head round this example so I will do my best to explain it.

max is a method with modifiers public and static. Its return type is the generic type T.

Generic methods declare a type parameter list which goes in between the modifiers (public static) and the return type (T). The type parameter for max is  T extends Comparable<? Super T>>. This means that T is type that is comparable with itself or its super class.

To break this down, let’s consider the simpler parameter type T extends Comparable<T>>. In this example, T is the type that is comparable with itself only. Adding the bounded wildcard type <? Super T> allows T to be comparable with its super types as well. This is necessary if we apply T as a class that subclasses a class E that implements Comparable<E>. One example of this that the book gives is the java.util.concurrent.ScheduledFuture interface which is a sub-interface of java.util.concurrentDelayed. Delayed extends Comparable<Delayed> whereas ScheduledFuture does not extend the Comparable interface directly.

The final brain teaser is the sole parameter list of type List<? Extends T>. This means that list can be a List of any type that is a subclass of T (remember everything is a subclass of itself).

Phew, I hope this made some sense. Please appreciate I’m hardly an expert in this field, so if you spot an error in my description then let me know!

Aptitude Woes

I’ve just spent the last hour battling with Ubuntu to get it to upgrade. My problem stems from installing the World of Goo demo and then removing it (it never had a hope in hell of working on my ATI graphics card). Now every time I try to install a new package through aptitude, or try to perform an upgrade I receive

files list file for package `worldofgoodemo' contains empty filename

I had to remove

/var/lib/dpkg/worldofgoodemo.list

to fix it. Not the most elegant solution, but at least I can install things again.

Last year I attended a talk by Richard Stallman in Manchester, UK where he explained the motivations behind Free Software as well as its history and what we could do to support the cause. Whilst I enjoyed the talk and agreed with most of his views, I found myself hooked on obvious marketing anomalies.

First of all, there is the name – FREE SOFTWARE. Most people in the audience assumed (even after Stallman reiterated the point on several occasions) that it’s all about not paying a penny, when of course the name refers to the FREEDOMS to run, modify, redistribute and improve the program. Surly, calling the movement something like FREEDOM SOFTWARE or LIBRE SOFTWARE (See Gratis versus Libre) would cause less confusion?

A further negative consequence of the confusion caused by the name FREE SOFTWARE comes about as a result of the psychological weakness of human beings to perceive quality in terms of price. When I’ve tried to explain Free Software to the casual computer users/business people (not programmers), their immediate impressions of the name is that the software is free (gratis) AND THEREFORE there must be something wrong with it. Like the GNU OS is some cheap knock-off of MS Windows! My point is that the name FREE SOFTWARE creates unnecessary hurdles to climb when we are trying to pitch the benefits of Free Software to a wider audience.

Now I’m done ranting, I will balance the karma by advertising a Manchester Free Software event this evening – Dan Lynch, Audio Production with Free Software – 21st July. I hope to see you there!

You may think this is an oxymoron, for example, I was having a conversation with one of my hippie friends a few weeks ago about how trade would operate if we got rid of money.

He believed that we would no longer need marketing, or marketing would become redundant because people would be completely free to choose what product/service to use and that if no one used your product then it didn’t matter. I found this view to be rather depressing – if we are living in a utopia where we are free to spend our time working on a project of our own choice, I would make it the best damn thing ever! More than that, I would aim for my product to change people’s lives for the better. The last thing I would want is to have my life’s work sit in a cupboard for the rest of eternity.

What I’m trying to say is that marketing is important for Free Software now and in the future. Even in a non monitory environment, healthy competition still exists, e.g. KDE v GNOME, which is beneficial to everyone providing innovations are not monopolised and restricted e.g. Apple patenting multitouch for phones.

Having well known intellectuals such Steven Fry on the GNU homepage is one nice way to market free software, but a lot more marketing is needed for free software to be successful.

/usr/share/doc

I’ve just stumbled upon /usr/share/doc! After 4 years of using Linux, battling with extremely terse man pages and obscure info documents, I have finally found some helpful documentation.

Admittedly, many of the folders only contain an AUTHORS and a README file, but some contain manuals in formats such as html.

I would highly recommend having a poke around, particularly if you need an offline version of a manual, or if you just installed a documentation package from a repository and wondered where it went!

Blip.fm

I just wanted to make a quick post, to try out the Blip.fm embedded player. Unfortunately, WordPress doesn’t allow its hosted users to embed flash movies, so the best I can do is to show you a link to my Blip.fm Player.

Blip.fm is a social networking site, similar to Twitter but to say what song you’re listening to. Seems like a simple idea? Why didn’t I think of that?

You search for a song, add a comment and it will play in your browser in quite a decent quality. It will also recommend other users or “DJs” who have similar music tastes, so you can listen to what they are blipping.

It’s quite a good way to find new music and see what your friends are listening to.

The website still needs a bit of work on the usability side though. I sometimes get a bit confused as to what playlist I’m listening to, or why the music coming out of my speakers is utter crap. It is also quite annoying when you’re typing in a song to search for and the homepage refreshes, meaning that you have to stop typing for a few seconds.

Now I found out about Blip through PC World’s article about the top 10 up and coming websites of 2009, which was voted straight to the top of Digg. However, Reddit recons the website is a bit dodgy. Just how are they able to give all this content away for free? The answer is that Blip.fm doesn’t own the content – you do! Any song you listen to, you must own, even though the website encourages you to listen to other user’s songs.!

We will have to wait and see if they manage to “iron out” this small detail, but in the meantime, give it a go 🙂