February 17, 2003
Bruce Eckel Thinks Checked Exceptions are Bad
And I think he’s right
Checked exceptions aren’t necessarily bad, they’re just misused. A lot. Part of the problem is that all the documentation on the subject gives the impression that RuntimeExceptions are somehow more serious than checked exceptions, so most developers tend towards writing and throwing checked exceptions. Imagine the reverse: only a situation so serious that the calling code MUST decide what to do about it warrants a checked exception. Checked exceptions force the developer to explicitly deal with them, or declare that they don’t want to deal with them. Either way, a choice must be made. RuntimeExceptions on the other hand can be ignored, and collectively dealt with at some higher level in the application.
Doesn’t that make more sense?
Explicit casts. I wish there was a compiler option that could make it flag these as warnings (or even better, errors). These hateful things sit there like timebombs in your code, just waiting for an opportunity to explode in a shower of ClassCastExceptions. They are at their most potent when buried somewhere in an infrequently used portion of the application, sometimes waiting for days or weeks until an unsuspecting tester (if you’re lucky) or user (if you’re not) stumbles across them.
They’re often not easy to get rid of. The approach I take is to try and extract out all the places something is being cast into a single method, and funnel all the calling code through that. Once that is done it gets easier to see how to remove the cast completely.
Added later: Obviously its impossible to entirely remove casts when dealing with things like collections. The best you can shoot for is exactly one cast per collection access, by wrapping up your collection accessor calls inside more type-specific methods.
This article from Sun (found here) has proved itself useful in solving a wierd problem that bugged me for over an hour earlier this week, whereby everytime I tried to hide some text that a third party component was printing (by making it the same colour as the background – per the vendors docs) it caused a totally unrelated section of the display to vanish as well. I finally fixed it by passing the component a font with zero size, but it turns out that the Graphics object has a handy ‘create’ method for making copies which can be used to isolate components from each other. It would appear that the supplied component made some changes to the Graphics object which were infecting other parts of the display. I love it when a mystery is solved.
One caveat: the ‘destroy’ method mentioned in the article is actually called ‘dispose’. Always write code samples inside an IDE!
Some thoughts on testing while I’m waiting for my commit email from CruiseControl…
Inversion of Control: Pass stuff as parameters, don’t instantiate objects inside methods just to make queries on them. It makes it much easier to use mock objects or stubs if the things you need are passed as parameters. If I had to come up with a pithy catchphrase for this it would be something like: “Methods should only create objects that will be returned from the method.”
This leads me neatly onto my other thought for the day – “Tell don’t ask”. Code should look like a sequence of commands, not a bunch of questions. If all you are doing is querying an object about its state, shouldn’t that code be inside the object? I think the anti-pattern is called something like Feature Envy, or Data Envy or something. Code that follows the ‘tell don’t ask’ principle is generally more polymorphic, more modular and easier to refactor.
I’m not talking about putting up a couple of wonky shelves here. Oh no. As you may recall, I had been without heating or hot water for three weeks. The repairs were covered by British Gas, who eventually (after several ‘robust’ telephone conversations) sorted someone out to fix it last monday. This involved moving the lounge radiator to a different wall and running a new section of pipe to it. As a result I was left with two pretty deep holes in my floor (which is concrete, despite being on the second floor). My cover didn’t include making good, so this weekend it was off to B&Q and a spot of repair work. It was not a good day. And my choice of career was once again vindicated – I would be a truly awful builder.
Most of the day was spent either (a) panicking, or (b) waiting. I now know far more than I ever wanted to about how to prepare a concrete floor for filling, including the exact ratio of water to PVA needed to seal it (3:1) or form a bonding coat (1:1). I also know that self-leveling floor filler requires a hole deeper than 6mm to be filled with pea gravel to a depth of 5mm below the surface. Fascinating. Hah.
Of course no DIY story would be complete without a humorous cock-up, so I went the extra mile and had two. Firstly, about halfway through the day I locked myself out of my bedroom when the door first swung open, hitting the door stop (which is at the exact height to activate the push-button lock thingy on the inside handle), then swung closed. With my keys inside. That was the low point of the day. I took a screwdriver to it. It didn’t last long.
The second error was failing to realise just how much filler it would take (despite buying a huge tub of it, which I thought would be about 50% too large), leaving the second hole with about a centimetre to go. Naturally by this time it was too late to do anything about it. Luckily I was too drained to care. But on the bright side, it does mean I get to have almost as much fun tomorrow evening as I did yesterday. Can’t wait…