Tuesday, 23 May 2006

Immutable POJOs - Improving on getters/setters

So we all know the bean/POJO get/set convention right? Its fine for mutable objects, but what about immutables? The convention just doesn't work there.

BigDecimal base = new BigDecimal(100d);
base.setScale(2);  // BUG!!!

Why is the above a bug? Because BigDecimal is immutable, and so the set method doesn't actually change base. Instead, the method returns a new BigDecimal instance which isn't being assigned in the example. Here's the fixed version:

BigDecimal base = new BigDecimal(100d);
base = base.setScale(2);  // FIXED by assigning

In addition, by returning a new instance, the set method actually breaks the JavaBean spec. This is because the JavaBean spec says that set methods must return void.

So what can be done? Well I'd like to argue that the time has come for a new coding convention for immutable beans/POJOs. As a convention (preferably Sun endorsed) it would allow frameworks like JSF or Struts to handle immutable objects properly. So, what do I propose?

Mutable verb   Immutable verb
get get
set with
add plus
subtract minus

Here's an example of a datetime object using these conventions:

DateTime dt = new DateTime();

// immutable get is the same as a mutable get
int month = dt.getMonthOfYear();

// immutable sets use the 'with' verb
dt = dt.withYear(2006);
dt = dt.withMonthOfYear(5);
dt = dt.withDayOfMonth(23);

// immutable add or subtract using the 'plus'/'minus' verbs
dt = dt.plusYears(1);
dt = dt.minusDays(1);

// combinations, for example, the first day of the next month
dt = dt.withDayOfMonth(1).plusMonths(1);

If adopted as a standard, there is even the potential to write a PMD or FindBugs rule to match on the verbs and ensure that you actually assign the result, thus eliminating a potential bug.

So, do you use immutable objects? Do you have a coding convention like this? Should this become a Sun convention? Opinions welcome!

Tuesday, 10 January 2006

Maven SourceForge Plugin v1.3 - Rapid releases!

Well my latest little project is complete - the Maven SourceForge plug-in. Basically all I've done is reactivated an existing plug-in and made it work with the latest SourceForge website.

So what does it do? Well it allows project administrators and release managers of open source projects hosted at SourceForge to use maven directly to upload their releases. The plug-in

  • Uploads the files (configurable set)
  • Logs on to the website
  • Accesses the File Release System
  • Uploads release and change notes
  • Sets the file types
  • Sends email notification (optional)
  • Submits a news item (optional)

Typically it manages this in a couple of minutes. Now thats a lot faster and a lot less hassle than doing it manually!!!

I've already released two Joda-Time subprojects as well as the maven-sourceforge-plugin itself so I'm pretty happy that it works. So next time you want to release something to SourceForge just do 'maven sourceforge:deploy'.

Friday, 30 December 2005

Joda-Time subprojects released

I've just finished releasing the Joda-Time hibernate support (0.8) and Joda-Time JSP tags (0.9) subprojects.

Both these projects are still officially pre a 1.0 release, however its good to have them available properly. I had intended to release the jsptags project as 1.0, but a cunning plan ensued which caused me to go to 0.9 instead. Hopefully I can confess what I've been up to soon, its really very useful!

Thursday, 22 December 2005

Joda-Time 1.2 is released

I had hoped it might have been released before Javapolis, but time pressures came into play (no pun intended!) Anyway, Joda-Time 1.2, the replacement for JDK Date and Calendar, is now released!

This release fixes a few bugs and upgrades to the latest time zone information. It also includes two new calendar systems, Ethiopic and Islamic. I am still looking to expand the range of calendar systems though, there are numerous ones still to add.

Also added were convenience methods on properties to create an interval for a whole month/week etc (toInterval), and to set a date to the last day in a month (withMaximumValue).

The feedback from Joshua Bloch and the rest of the audience at Javapolis was useful, and I expect to enhance and clarify the API over the coming year.

Full details can be found on the website. As always, feedback welcome!

Sunday, 27 November 2005

Changing Java: Adding simpler primitive creation

So, when you're coding in Java sometimes you just have to use primitives. (We'd all love to use objects all the time, but that just isn't possible in Java). However creating primitives can be a pain on occasion, so what could we do?

Defining a variable/constant is easy and just works for short/byte (and all types):

// defining variables is easy:
double val1 = 2.1d;
float val1 = 2.1f;
long val1 = 2L;
int val1 = 2;
short val1 = 2;
byte val1 = 2;

However calling a method shows us the nasty difference between bytes and shorts compared to longs, floats and doubles:

someFloatMethod(2f);  // compiles OK
someShortMethod(2);   // doesn't compile
someByteMethod(2);    // doesn't compile
someShortMethod((short) 2);  // compiles OK
someByteMethod((byte) 2);    // compiles OK

public void someFloatMethod(float f) {
}
public void someShortMethod(short s) {
}
public void someByteMethod(byte b) {
}

So why do we not have a convenient shorthand for bytes and shorts like the 'f' for float or 'd' for double?

someShortMethod(2s);  // note the 's'
someByteMethod(2b);   // note the 'b'

public void someShortMethod(short s) {
}
public void someByteMethod(byte b) {
}

A related issue is creating a binary value (which I needed to do tonight - bonus points if you can guess the pattern I was storing!):

int binary =
    (1 << 2) + (1 << 5) + (1 << 7) + (1 << 10) +
    (1 << 13) + (1 << 16) + (1 << 18) + (1 << 21) +
    (1 << 24) + (1 << 26) + (1 << 29);

Yuck! Why could I not create it with a specialist syntax like this:

int binary = 0b00100101:00100101:00100100:10100100;

While not suitable for every case that you want to create a binary value, it definitely has value. The question is whether its too minor a use case to justify a language change?

Thursday, 24 November 2005

Adding for loop indexing to Java

When using the new for loop in JDK 1.5 do you ever need an index? What do you do, and could a language change help?

Collection coll = ...
int i = 0;
for (String str : coll) {
  System.out.println(str + ", line " + i);
  i++;
}

This isn't very friendly, and exposes the loop index outside the scope of the loop. Maybe we could have a small language change:

Collection coll = ...
for (String str : coll : int i) {
  System.out.println(str + ", line " + i);
}

Note that the extra : int i would be optional! If you don't want the index, just don't declare it.

This is really just a logical extension of the enhanced for loop change from JDK 1.5. Its main benefit is protecting against stupid errors with the scope of the index when an index is actually needed.

Something else that was lost with the new for loop was the ability to remove an item from the collection using the iterator. A variation on the index syntax would allow us to reinstate that:

Collection coll = ...
for (String str : coll : Iterator it) {
  if (str.startsWith("org.apache.")) {
    it.remove();
  }
}

There are more issues with this one however, as Iterator also exposes the hasNext and next methods which the for loop is using. This shouldn't cause a problem, but might require some more work in detailed design.

This blog is number 4 in a series on possible language enhancements to remove boilerplate code - see code blocks, nulls and casts. Opinions welcome as always :-)

Wednesday, 23 November 2005

Adding auto casts to Java

OK, so after auto null checks and code blocks what else would make Java that little bit clearer to read and write? What about casts?

Once again, here is an example use case:

public int getAge(Object obj) {
  if (obj instanceof Person) {
    return ((Person) obj).getAge();
  }
  return -1;
}

Note, I've deliberately kept the use case 'stupid'. There are many good OO solutions to this kind of problem, but I believe that the vast majority of Java developers still end up writing nasty casts all the time.

So, what do I propose could be changed in Java 1.6?

public int getAge(Object obj) {
  if (obj instanceof Person) {
    return obj.getAge();
  }
  return -1;
}

The compiler can easily figure out that obj must be an instance of Person in the if statement. So why do we need the cast? The code without the cast is more readable and just as safe.

I still believe that casts have a useful role to play in Java, when you want to emphasise a point in conversion, or to cast without an instanceof. But when we've already checked with the instanceof, why are we have to repeat ourselves? Thats just boilerplate code.

Opinions welcome, as always.