The Artima Developer Community
Sponsored Link

Josh Bloch on Design
A Conversation with Effective Java Author, Josh Bloch
by Bill Venners
First Published in JavaWorld, January 4, 2002

<<  Page 9 of 19  >>

Advertisement

Being Forgiving

Bill Venners: OK, enough of trust. How about forgiveness? To what extent should I be forgiving of clients? For example, imagine a constructor that takes an array of Config objects. Should I allow nulls in that array? I could document clearly that null elements are allowed and simply ignored. Maybe allowing nulls makes the class easier to use, but on the other hand, it may also be missing an opportunity to catch null reference bugs earlier.

Josh Bloch: I think you pretty much answered your own question. I agree with the latter observation. Basically, I think this is one of these specious things. Some people claim they want this freedom, but in practice, once they have it, all it does is masks bugs. Also, there are general conventions for these things. In Java, the convention is not that null means a zero length array. null means null. If you pass a null to something, it often invokes a method on it and throws a NullPointerException.

If an API allows nulls to exist longer, it isn't doing you any favor. It's just pushing the exception off to the next API that you pass the thing to. Often, it's better to just enforce the rules uniformly. Some people will complain, especially because the convention isn't completely universal. There are APIs that do let you pass around nulls as an abbreviation for zero length arrays or for an empty string, etc. And those APIs are in a sense bad citizens, because once you mix them with APIs that don't, you're in trouble.

This is one of these few places where I feel like some sort of puritan. But I have found that it's easier to write robust correct systems if you are maybe a little less forgiving on input. On the other hand, this is a controversial issue and the greater the variety of clients you have to operate with, the more forgiving you should be. For example, if a browser threw up its hands every time it hit bad HTML, that would be a disaster. There are millions of people writing HTML, and many of them have no clue how to write syntactically perfect HTML.

Bill Venners: That's true, but on the other hand most people probably look at their web pages in a browser before publishing them. If the browser didn't work until the HTML was correct, then you'd probably have much less bad HTML on the web. And this issue is not not just about nulls. It's a general philosophy issue in design. I've met people who say you should be forgiving. If somebody passes something that's a little weird, you make assumptions about their intent and go on, instead of throwing an exception and killing everything. They think it is better to try and keep going than to bring everything to a screeching halt.

Josh Bloch: One of the biggest problems with forgiveness is you start to lose precision. Often the specs on what can come in are designed to let you precisely state your intentions. If you get something that isn't syntactically valid and you try to intuit what the programmer's intentions were, you may come up with something that does not match their intentions. That's why we have formal languages. There are places where we are utterly unforgiving.

For instance, if you look at Integer.parseInt, it does not tolerate leading or trailing white space. Occasionally, people complain about his, but I think it can be justified on these grounds. There's a precise definition for what constitutes legitimate string representation of an integer, and that's what you have to provide. Generally speaking, I find the things that are looser are the ones where we get into trouble.

An extreme example of this is the persistent form of Properties. The store and load methods of class java.util.Properties emit properties to disk and pull them in. The on-disk format tries to be forgiving, but it doesn't do a terribly good job of it. If you look at the bug database, you'll probably see tens if not hundreds of bugs having to do with the inability to get something reasonable on input when you output some properties and edit them, or take them from one locale to another, or one system to another.

The reason for all these bug reports is that we didn't write a BNF for the property file format. If we had just said, "Look, this is the syntax of a legitimate on-disk properties file. Obey it and you'll have no problems," that would have been great. But we didn't do that. Instead, we said, "This is roughly speaking what a legitimate on-disk properties file is, and we're a little flexible in what we accept." In practice, there is no clear demarcation of what constitutes legitimate and what doesn't. And there is no clear mapping from what's on disk to the actual logical object.

If you look at Preferences, which is a replacement for Properties, you'll see that it uses XML with a DTD as it's on-disk representation. And there's no doubt as to what constitutes a legitimate Preferences document. Either it is or it isn't. Either it obeys the DTD or it doesn't.

<<  Page 9 of 19  >>


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2009 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us