Wednesday, June 28, 2006

XP Day 6

The details of this year's XP Day conference have been announced. The conference will take place on 27th-28th November, in London, UK. If the past years are anything to go by, this should be an excellent event. The style of the conference is such that most of the sessions actively encourage participation by the delegates, normally through some sort of interactive exercise. This is a great way to learn, and to get to know new people.

I am helping to organise the programme for this year's conference, and we are now looking for people to submit suggestions for sessions they would like to run. Full details of what we are looking for, and instructions for how to submit, can be found in the call for proposals. The closing date for submissions is August 14th, so get thinking.

Monday, June 26, 2006

Update - generics puzzles

After my post yesterday, Tristan Allwood and Nick Cameron both wrote to offer some help. When you want a list of things that implement both interface A and interface B, the syntax that you need is: List<T extends A & B>. Yes, that's an ampersand. Ugly isn't it. To make matters worse, this syntax doesn't mix well with wildcards, so you can't write List<? extends A & B> . Instead you have to write <T extends A & B> void m(List<? extends T>) { ... } .

Sunday, June 25, 2006

More generics puzzles

This week I had a couple of interesting discussions with people about some particular points of programming with Java generics. The first case was that a developer wanted to write a method that processed a list of objects that implemented two interfaces. He wasn't concerned with the actual class of the objects, just that they implemented the two interfaces in question. This seemed to be a case for the use of wildcards, where we can specify a method as taking a paramater that is, say, a List<? extends A>. However, it doesn't seem to be possible to write something like List<? extends A, B>, even when A and B are interfaces rather than classes.

Some might say that a method should only act on an object through one of its interfaces, and that any processing using the other interface should be encapsulated in a separate method, but this is a matter of design, and it does not seem that it should be being enforced by the type system. Also, it seems unlikely that this is the reason that Java does not support this.

In the end, the best solution we could come up with was to create an interface C that extended A and B, and to make the objects to be processed implement this interface instead. The source of these classes happened to be under our control so we could do this, but it didn't seem like an optimal solution, and there are many cases where it could not be used.

The second case, was where a different developer was writing a unit test using jMock mock objects for the collaborators of the class under test. In this case, this meant that he needed to mock a generic class, as the class under test had a setter method that takes a particular instantiation of the generic. So we had code along the lines of:

class X {
setK(K<String> k) {
...
}
}

class TestX extends MockObjectTestCase {
void test() {
X x = new X();
Mock mockK = mock(K.class);
x.setK(mockK.proxy());
}
}

The first thing to notice is that we cannot write mock(K<String>.class). See an earlier post for an explanation of why not. Therefore we have to mock K.class. First of all, we wondered whether this would work, especially as we were using the cglib variant of the jMock library, but in fact it did. The interesting part is that in the above code, we have to cast the result of mockK.proxy() in order for it to compile. The most obvious thing is to cast it to a K<String>. But, using Eclipse, we get a warning that says that our cast is "actually checking against the erased type". This is true, as after compilation the generic type information is not present, so there is no way to check this cast at runtime.

If we make the cast a bit less specific, and just cast to a K, then we get a different warning, saying that we need an unchecked conversion to conform to the signature of the method that we are calling. It seems there is no way we can win, and the only way to keep Eclipse happy is to add an annotation to the method to suppress the warnings - not ideal.

To some extent, these problems were caused by the fact that jMock is written using the Java 1.4 API, and so does not have inbuilt support for generics, but this is not the only cause, and it seems to be a common case that generic code is interwoven with older, non-generic code. These sorts of examples certainly show that the Java generics, and the supporting type rules, can be somewhat puzzling.

Wednesday, June 21, 2006

London Test Automation Conference

A well-known search engine is hosting the London Test Automation Conference in September. Tom and I were pleased to be invited to present our experiences using the literate testing style that we have been working on recently. Hopefully it'll be an interesting event, although the full programme has yet to be announced, so we don't know who else will be there yet.

Thursday, June 15, 2006

Carnival of the Agilists

Kevin Rutherford has been putting together a fornightly round-up of agile topics being discussed in the blogosphere, which he calls Carnival of the Agilists. We got a mention in the current edition, thanks Kevin. There's also some interesting stuff from Liz Keogh and Joakim Karlsson amongst others.

Wednesday, June 14, 2006

Brian Marick's Sentence Style Tests

Brian Marick has also been thinking about making tests more readable (also inspired by jMock). He mentions what Tom and I have been writing about (thanks Brian). His tests are perhaps more readable because a lot of the functions are written to explicitly test particular cases, e.g.

page.main_text.should_have_no_list_named(:visits).
should_have_no_list_named(:audits).
and_should_have_a_help_popup_named(:patient_display_page)

so the logic or quantification is combined with the noun he is trying to match, in the same statement. We have tried to construct more general building blocks, which means we tend to have rather more nesting of clauses. Also, Brian benefits from the fact that he is using Ruby rather than Java, so the syntax is somewhat less cumbersome.

This page is powered by Blogger. Isn't yours?