Wednesday, 23 August 2006

Extension methods and closures

Extension methods are a C# feature that just could prove very useful in Java, particularly with the possibility of closures in Java (something which should be the topic of a blog in its own right). So, what is an extension method, and why might it be useful? Consider the following code:

public class Collections {
 pubilc static void sort(List list, Comparator comp) {
   ...
 }
}
public MyClass {
 pubilc void myMethod() {
  List list = ...;
  Comparator comp = ...;
  Collections.sort(list, comp);
 }
}

This is standard JDK code. To sort a list you have to use the Collections static methods. But that means you need to know that they exist there - they won't auto complete like other list methods in an IDE for example. What if we could find a way to alter this slightly.

public class Collections {
 @extensionMethod(Sort)
 pubilc static void sort(List list, Comparator comp) {
   ...
 }
}
public MyClass {
 pubilc void myMethod() {
  List list = ...;
  Comparator comp = ...;
  list.Sort(comp);
 }
}

So, by adding an attribute (or some other syntax mechanism - C# uses 'this' rather strangely) and importing the Collections class, we can then call the sort method in an OO style in the client code myMethod(). I have deliberately setup a coding standard, so that the extension method has a capital first letter. This would allow someone reading the code to spot that it is not a standard method on the class. Behind the scenes, all it does is call the static method in a static way - no magic involved.

This brings benefits in being able to effectively extend code that is locked down in some way - perhaps because its an interface (such as the JDK List interface), or perhaps because its an 3rd party library that you don't want to change, but is really missing a very useful little method.

So, how does this link to closures? Well, many closure advocates want to add methods to Collection, List and Map to allow closures to operate directly on the collection. But this simply isn't going to happen as they are interfaces and backwards compatability must be maintained. However, extension methods offer a solution - a way to apparantly add methods to the collection interfaces. Thus you could code with closures:

public class Collections {
 @extensionMethod(Each)
 pubilc static void each(Collection<T> list, void(T) closure) {
  for (T item : list) {
   closure(item);
  }
 }
}
public MyClass {
 pubilc void myMethod() {
  List<String> list = ...;
  list.Each() (String str) {
   System.out.println(str);
  };
 }
}

So, are there any views about extension methods? Are they really an essential addon to the closure proposal?

Which days of the week are the weekend in Egypt?

Do you know? Or more precisely, does your Java application know?

Well, yesterday I released a 0.1 version of a new project Joda-Time-I18N. This provides four lookups at present:

  • Time zone by territory
  • First day of week by territory
  • Business days by territory
  • Weekend days by territory

The data comes from the Unicode CLDR project, so should be pretty accurate (its backed by IBM and Sun).

The code is released now to get some feedback, and to allow early users access. The 0.1 version refers to the chance of the API changing (high), not the quality of the data (which is good). Oh, and the weekend in Egypt?

  Territory t = Territory.forID("EG");
  int weekendStartDay = t.getWeekendStart();
  int weekendEndDay = t.getWeekendEnd();

Anyway, I'd love to here any feedback on the API, data or proposed enhancements.

Wednesday, 2 August 2006

Joda-Time 1.3 released

Well, it took a while, but the next release of Joda-Time is finally here. Version 1.3 includes two main enhancements in addition to the bug fixes:

Three new datetime classes have been added - LocalDate, LocalTime and LocalDateTime. These represent a date, time or datetime without a time zone. As such LocalDate is a direct replacement for YearMonthDay, whilst LocalTime replaces TimeOfDay. Neither of the replaced classes has been deprecated yet however, due to their widespread adoption.

The new Local* classes use a more standard and reliable implementation internally, and fix some weird external semantics of the older classes. For example, it was not possible to query the dayOfWeek on a YearMonthDay (because it only holds year, month and day!). LocalDate uses a different implementation, so that restriction no longer applies.

The second major enhancement is the addition of convenience methods to change each field value - immutable equivalent of set methods. Here is how to set the day to the first day of the month, constrasting before and after:

// previously
firstOfMonth = dt.dayOfMonth().setCopy(1);

// version 1.3
firstOfMonth = dt.withDayOfMonth(1);

Clearly, the new code is more readable and understandable. Note that as Joda-Time objects are immutable, the methods return a new instance with that field value changed. This is emphasised by the use of the verb 'with' rather than 'set'

As always, feedback is welcomed - whether bugs or reviews, good or bad! Only with input from the community can the library improve.

Monday, 31 July 2006

Generics - why no <this>?

So, am I just misunderstanding the spec, or is there no way to easily specify that a method should return the type of the object you called the method on?

Consider this example - I want to write a whole heap of methods in an abstract superclass, but I want each method to return the type of the subclass:

public abstract class A {
  <this> withYear(int year) {
    // implementation
  }
}

public class B extends A {
}

B b = new B().withYear(2006);

But, there is no <this> part in generics. The closest I could get was to generify the whole type (A) based on its subclass (B). But thats not really what I want to do at all.

Am I missing something?

Thursday, 6 July 2006

A better datetime library JSR?

Do you hate the JDK Date and Calendar classes? Would you like to see an alternative in the JDK? Or are you happy with the JDK classes? Maybe you are happy with pulling in a jar file?

I ask because I get asked from time to time whether Joda-Time is going to get a JSR. Each time this comes up I point out that its a lot of work to do in my free time, and there are infrequent enough releases as is!

So, this blog is an open question - is it worth it? Should JDK7 contain a better datetime library? Please add a comment with your views, postive and negative so I can get some idea of peoples thoughts!

Friday, 16 June 2006

Generics and commons-collections

A debate has started up over in Jakarta-Commons as to whether a new version of commons-collections should be created that supports JDK1.5 generics.

Unfortunately, I happen to think that generics (as implemented) have serious flaws. There are just too many weird behaviours and odd corner cases. Just look how big the FAQ is - a sure sign of serious problems. And they also look darn ugly too!

A forked version has been created on sourceforge with generics, but that is far from ideal, as Apache can't link to it (official policy) nor can it easily be kept in sync. However, it does show that the task is possible. Could the fork be brought back to Apache? Well possibly, but that gets bogged down in bureaucracy when the forkers don't have Apache commit priviledges. Even more so when the relevant Apache committer (me) isn't particularly motivated by the issue (generics).

Anyway, I'd like to ask anyone reading this a question or two - do you want a generics JDK1.5 version of commons-collections? Would you mind if parts of the API were changed to fix API design flaws (this would be a major release after all...)? Please comment here, or at Commons JIRA. You can also just vote for the change at JIRA.

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!