Tuesday, September 29, 2009

The Java language feature I want: Exception Sugar

I've enjoyed observing all the discussion around the new features to make it in to Java 7. All this time I've had an idea about a language feature which I've occasionally mentioned to colleagues, and it's around the domain of exceptions.

Before I discuss the problem, or my proposed solution, let me be frank: I'm no language expert. I have no expectations that a suggestion such as this has a chance of getting in to Java 8 if they can't even get multi-line strings into Java 7. I don't even care about the impurities brought up by this proposal. What I do care about is discussing a more graceful way of dealing with exceptions.

I'll agree with some of the fundamental concerns Misko Hevery brings up around the domain of checked exceptions. People often don't know what to do with them. Sometimes people just throw Exceptions into RuntimeExceptions and propogate them up the call stack. People also tend to overuse existing exception classes when one more specific to the a class or API domain would do. As is well documented in Effective Java (2ed) Item 61: Throw Exceptions appropriate to the abstraction. However, this all too often requires an undesirable amout of boilerplate code, and I do mean boilerplate. How many Exception classes have you written that look like this?
class MyException extends RuntimeException {
  public MyException() { super(); }
  public MyException(String message) { super(message); }
  public MyException(Throwable cause) { super(cause); }
  public MyException(String m, Throwable c) { super(m, c); }
}

Unless all your methods throw Exception, or if you only throw RuntimeException, IllegalArgumentException, and AssertionError, the answer is: you've written them plenty of times, and unless you're building an API to be consumed by the tens of thousands of engineers, you're probably not creating abstraction-appropriate exceptions often enough, directly against the advice of Effective Java.

What I propose is lowing the barrier for creating an exception class, which I'm calling Exception Sugar. Again, being no language maven, with no regard to syntax or grammar, I humbly propose:
exception className extends baseClass;
which serves as syntactic sugar for creating a subclass of baseClass named className that also, and here's the nasty part, "inherits" the base class's constructors. Yes, I know damn well that constructors aren't methods; they don't have instance scope, and there's really no such thing as constructor inheritance. I read Jeremy Manson's blog, and he even talks about the worthlessness of constructors. I get it. I couldn't care less. I just want to make it easier to write exception classes. To avoid the term inheritence I'll call it constructor propagation.

Maybe you don't like the proposed syntax. What about:
class className extends baseClass { propogate_ctors(); }
or
@ExceptionSugar className extends baseClass {}
Did you hear that? That, my friends, was the sound of a thousand shattering coffee cups from Java programmers whose grips loosened uncontrollably from the awful syntax. Relax, girls and boys. I'm not trying to sell syntax. I'm just trying to sell an idea. Get over the syntax, and mop up your coffee.

Q: Why can't you write your own exception class?
A. I might get it wrong. And I want to do it a lot. I want to make creating a domain-specific exception class even easier than creating a class for the domain.

Q: How could you use Exception Sugar to create subclasses that have additional attributes, or slightly different constructors?
A: I don't have any illusion of doing so. It seems to me that 99% of the time, people want to subclass Exception or RuntimeException, and even then, they only define just one constructor instead of all four.

Q: Why can't constructor propagation be applied to non-exception classes? Why should exceptions be the, ahem, exception?
A: Ha ha nice one. They don't have to be, but I'm not interested in easily propagating for classes outside the exception hierarchy. But if I'm pressed, constructor propagation in non-exception classes is almost certainly a Bad Idea, but am not going down that path tonight.

Q: Why not focus on something more valuable, like properties?
A: Properties sounds like a good idea. Go for it. The reason I bring up this particular idea is because I don't see anyone else thinking about it. That isn't to say I haven't brought it up before. I even mentioned it to Alex Buckley at last year's EclipseCon. Poor Alex, it was 1:30AM, and he and I somehow managed to win the party that evening, and so he had to suffer listening to yet another armchair language designer. But I will say, when I mentioned exceptions, he thought I was referring to catching multiple exception types. At least he was surprised, which means the idea might be awful.

Or awfully brilliant!

To be fair, Alex described some of the details that demonstrate the difficulty of this idea, but the combination of many drinks and the late hour made it impossible to understand. (Sorry, Alex.)

But getting back to the value of such a proposal: if people can propose literals with underbars and the Elvis operator, I can talk about this, too. (Don't get me wrong, I very much want the Elvis operator.)

As a conclusion of sorts, I'm about 95% confident there's a technical reason for prohibiting Exception Sugar, and about 99% confident it would never make it in to Java. I'd be honored if someone with an understanding greater than mine of Java and language design would be willing to comment on this idea, and provide some thoughts about the technical issues, if at least to educate.

Thanks for reading. Thanks to David Mankin for his feedback.

5 comments:

varioustoxins said...

Hi i wondered if you have you looked at project lombok ;-) (projectlombok.org). Though it is a hack in some ways it does what you want or could be extended to do what you want... If nothing else it could be quite good for testing the idea in the hope that some other jvm language took up the reins

regards
gary

konberg said...

I did look at Lombok, but it's just not going to work for me unfortunately.

David Plass said...

Cool

Joel said...

This feature gets my enthusiastic support. I don't really have strong feelings about the syntax, but I wonder if some Scala/Erlang influenced pattern matching type of syntax would suffice. Then I could say:

class MyException extends SomeException {
protected final Foo foo;

public MyException(_, Foo foo) {
super(_);
this.foo = foo;
}
}

That would allow me to match all super class constructors in one shot and do the thing I'm really interested in (store a ref to foo).

konberg said...

Joel, nice to see you on the internet! FYI your dad loaned me his keyboard last month.