Archive for January 2007
The Evil Boolean Constructors
This is something straight out of the Effective Java book, which every, really, every Java developer should read. But I still find a lot of calls to Boolean constructors, to this very day, 6 years after the book was out. (Has doing code review turned me into a grumpy nagging old man or what?)
The twin constructors of java.lang.Boolean, namely, Boolean(String) and Boolean(boolean) should never be called from within your application. The only legit user of these two constructors is the Boolean class itself. The reason is simple: you only need two Boolean instances, really. One to represent true, one to represent false. That’s it. And these two objects already exist as class variables of Boolean, namely, Boolean.TRUE, and Boolean.FALSE. You only need these two.
You don’t need the constructors for converting from the primitive boolean and String either. There are two static methods available just for this purpose. Boolean.valueOf(String) and Boolean.valueOf(boolean). Instead of saying:
Boolean isMad = new Boolean(true);
Boolean isNotCrazy = new Boolean("TRUE");
say
Boolean isMad = Boolean.valueOf(true);
Boolean isNotCrazy = Boolean.valueOf("TRUE");
Because valueOf() returns either Boolean.TRUE or Boolean.FALSE, instead of creating another unnecessary Boolean instance. For the case when you already know whether to pass true or false, instead of saying:
book.setRegurgitable(new Boolean(false));
simply say
book.setRegurgitable(Boolean.FALSE);
So, be very suspicious of the existence of “new Boolean” in your codebase. If your code is based on JDK 1.4 or above, really, there shouldn’t be any “new Boolean” anymore, anywhere. In fact, if there’s a legit case when one just have to use the Boolean constructors in their code, please let me know, I’ll be grateful.
Effective Java Reloaded… Déjà Vu All Over Again
Well, almost. Here are the slides by the man himself, Joshua Bloch. He shared some new ideas on tackling the challenges we face in writing good, effective Java code.
A good read, but this is déjà vu all over again. Last time, I invested a lot of time and energy understanding the intricacies of C++, grokking all kinds of patterns that one should use to write good robust C++ code, reading good books by really smart C++ people, only to find that those problems were really C++ problems. The move to Java made perhaps 60% of those problems irrelevant.
So I was content with Java for a while. But now that I know languages other than Java, such as Python, Ruby, JavaScript, Lisp, my eyes have been irreversibly opened. These languages made me realize that things don’t have to be that way. The fact that you have to create a class for everything doesn’t mean that it’s right, for example. It’s perfectly OK to have first-class functions, like in JavaScript.
All those Java “solutions” are not necessarily breakthrough solutions that make you a better programmer. Some of them are merely solutions to problems you only find in Java. Moving to another language (say Python), will make a large percentage of them irrelevant.
How To Deprecate Things Like A Real Man. Or Woman.
So. You have this huge class doing complicated things with methods that take a bunch of arguments, and the author, for reasons obvious only to him, suddenly decided that he should deprecate the method that you’ve been using the most.
public class ReallyImportantClass {
/**
* @deprecated aMethodWithALotOfArguments has been deprecated.
*/
@Deprecated
public void aMethodWithALotOfArguments(String s, Long l, Integer i,
Object ... args) {
// do some really complicated things here
}
public void aMethodWithALotOfArguments(String s) {
// do some really complicated things here
}
public void aMethodWithALotOfArguments(String s, Map m) {
// do some really complicated things here
}
public void aMethodWithALotOfArguments2(String enc, String s, Long l,
Integer i, Object ... args) {
// do some really complicated things here
}
}
Okay. Maybe that was a little exaggerated. But you have encountered that before, haven’t you? It’s bloody annoying, especially when the call to that deprecated method is buried deep inside another long method and I… don’t… care… one… iota… what your method is doing… I just want to replace your freakin method with its successor and move on to another thing. Very infuriating.
So, let’s be considerate to our fellow programmers, shall we? When deprecating a method, always tell your users these:
- Which method replaces the deprecated method–this is the least we could do!
- How to call the new method so you have the same effect as the old one. This is very important for people who don’t care what your method does and just want to make sure they won’t get bitten when they upgrade to the next version of your library, which no longer have the deprecated method. They need to know how to make their program still behave the same with the new method. This is not always possible, alas. java.lang.Thread.stop comes to mind. Then at least document the alternative approach, eh?
- If the users of your class are your teammates in the same project, document why you are deprecating the method.
Going back to the example:
/**
* @deprecated aMethodWithALotOfArguments has been deprecated
* because it may not perform correctly under certain circumstances.
* Please use aMethodWithALotOfArguments2 with "UTF-8" as the
* first parameter to replace the call to this deprecated method.
* @see ReallyImportantClass#aMethodWithALotOfArguments2(String, String, Long, Integer, Object[])
*/
@Deprecated
public void aMethodWithALotOfArguments(String s, Long l, Integer i, Object ... args) {
// do some really complicated things here
}
The same goes for deprecating classes and fields. Let’s try to be more considerate to our fellow programmers!