Wednesday, July 04, 2007

Generics

In my last post, I discussed annotations, and their contributions to the Java language. The short version: they are pretty simple, and surprisingly useful. Generics, also introduced with Java 1.5, is a much larger pill to swallow. Not on the useful part, they are undeniably helpful. They do something very important, which is to make run-time errors visible at compile time, while at the same time increasing the self-documentation of code. This is a great thing. However, there is no doubt that they add complexity. To even document all cases of complexity would take a whole blog dedicated to just that subject. I'll give one example:

foo(List<B> list);
bar(List<? extends B> list);
tor(List<? super B> list);
So, what's the difference between these? Well, suppose B has a subtype C, and a supertype A. So the inheritance hierarchy goes A -> B -> C. You can call foo with a List<B>, but not a List<C>. But you can call bar with a List<C>; as well as List<B>. You can call tor with a List<A> and List<B>. Keep in mind that the contents of the list are not what I am talking about, just the compile-time type of the list.

Generics are a bit more complicated than most people assume. Almost anyone who has spent time with Generics has gotten into several puzzling situations that they can't explain, and where the solution isn't obvious.

The question I wonder about is whether it has done more harm than good. This is not a matter of opinion, I think. If we could count up all the hours of lost productivity in wrestling with generics, and count the hours saved by catching bugs and improving the clarity of the code, would the time saved exceed the time lost? My anecdotal evidence is that it is a net benefit. It has rescued the Java world from the perils of type-casting, and I do remember getting many ClassCastExceptions in the past. Nowadays they are rare, and I don't spend excessive time on the complexities.

Tuesday, February 13, 2007

Annotations

This post is a few years too late. Annotations came out in Java 1.5, and we already are on Java 1.6. But I'd like to make a few comments on them, because I think they are a great example of a low-cost but a high-use feature.

Making improvements to a popular language is always difficult. You want each addition in functionality to be well worth it. Each addition should make things possible that were not possible before, and do so in a way that both fits with the spirit of the language, and results in the least possible disruption.

Java annotations are a good example of a good change. I find I use them more and more, and they enable things I now realize I in fact need. Did I need them before annotations were around? It didn't seem so, but now they are here I would find it difficult to live without them.

I should illustrate how useful they are with a made-up example. Let's say you want a simple webserver, one that took the path and used it to call into a dispatcher object. So you would call http://localhost/doSomething?foo=aaa&bar=bbb. This would use Java reflection to call a method Dispatcher.doSomething(String foo, String bar) . But at reflection time you don't know the names of arguments, since those are all compiled away. So, the first challenge is to figure out which argument is foo and which is bar. How can we do this? Before annotations, I would say you cannot do this. You could do something such as populate a String to String map, and pass that in instead of arguments, but this is awkward for the non-reflection callers, and also doesn't enforce important invariants at compile-time. Luckily for us, we do have annotations, and the annotations stick around at runtime (if you want them to). So, we can make an annotation defined as:

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface ParameterName {
String value();
}

And we can use it like so:

void doSomething(@ParameterName("foo") String foo,
@ParameterName("bar") String bar) {
...
}


Now reflection can match HTTP parameters up to the method arguments.

But the fun doesn't stop there. What if you wanted your delegator class to only have some methods accessible from the web? You could try to separate into another class that is only web methods, but that overly constraining on the design. Or, you could maintain a separate list of web-safe methods in a configuration file. That solution seems prone to mistakes - developers will forget to update the configuration file, then wonder why their new method isn't accessible. However, with annotations, you can simply tag methods with an annotation showing that they are web-safe. We can create a runtime method-level annotation called WebExecutable and use it like so:


@WebExecutable
void doSomething(@ParameterName("foo") String foo,
@ParameterName("bar") String bar) {
...
}


Now, your dispatcher can check for the annotation before it executes. Instant safety! You can imagine further annotations that may classify whether methods needs authentication or not, or other such improvements.

I've really been digging annotations. They make things possible that never were possible before, and don't introduce much complexity or confusion. There is some new syntax to learn, and some non-obvious things (such as "@interface"), but all in all, the part you have to look at the most is very easy and intuitive. I think it's an ideal addition to the language.

Next, I intend to look at generics, which has quite a different profile.

Thursday, October 26, 2006

Language growth

To alter a quote from Annie Hall, programming languages are like sharks. They have to keep moving or they will die. Languages frequently don't succeed at this. Thus a fine language like Common Lisp failed to include threads and networking in its spec, and by the time standards emerge, it is too late; the needs of users have long since passed by.

Java has done a good job of this. They have managed to keep incorporating the needs of users, while trying to stay true to the spirit of the language, and they have not proceeded so fast that they introduce unncessary complications. Some of their additions to the language spec have made things more complicated and confusing, but you always get something out of it.

I'm interested in exploring this topic further in the next few posts. I'd like to explore a few examples of Java language additions, and then examine some potential upcoming changes. What are your opinions about changes in the Java language in recent years?

Thursday, October 19, 2006

Introduction

Not only is this yet another blog, this is yet another in a series of blogs by me. I'm a believer in blogs that suit a specific topic, and therefore this is my blog for technical topics. For a developer, having a technical blog is a way to both refine one's thoughts on particular topics, practice technical writing, and of course advertise oneself as being a knowledgeable dude.

Every blog should know who its audience is. This blog's audience is other developers, mostly those who are searching for topics. Although it would be nice to have people subscribing to my atom feed, I do not expect it.

I program primarily in Java, with some Python, and some dabbling in lisp. Expect posts relevant to those topics, as well as posts about development in general, productivity, IDEs, and similar issues. Do not expect a flurry of posts. I expect to be posting at least once every two weeks, but more if I happen to have a lot to say, or less if I am unusually busy.

Oh, and I actually hope that this will be a good blog, and will actually contribute some knowledge or something of value to the world.