Saturday, November 8, 2008

Programming in the small - Exceptions

It's a long time since I wrote my previous "programming in the small" article. This article is about Exceptions in Java. I've kept it very short just to cover the absolute minimum.

Handle or throw

What is likely to be wrong with this code?
    public void makeTea() {
        teaPot.prepare();
        try {
            kettle.boil();
        } catch (ElectricityCutOffException e) {
            LOGGER.log("Didn't pay bill; no tea today.");
        }
        kettle.pourContentsInto(teaPot);
    }

Logging that some exception has been thrown is not handling it. In this case, "pourContentsInto" will still be called even if "boil" threw an exception. The exception indicates a problem, and to keep executing will probably mean that the system is in an unknown, inconsistent or bad state.

In this case, I'll end up with cold water in the teaPot, ruining the tea in an unrecoverable way.

In many cases, catching an exception and not handling it causes bugs which are tediously difficult to track down because the system ends up in an inconsistent state and the exception that eventually causes the system to fail, or the error in its functionality, ends up being somewhere that looks completely unrelated to the code that caused the problem by hiding the exception.

If this method is a sensible place to fully handle the exception, then it should do that. For example:
    public void makeTea() {
        teaPot.prepare();
        try {
            kettle.boil();
            kettle.pourContentsInto(teaPot);
        } catch (ElectricityCutOffException e) {
            butler.sendToTeaShop();
        }
    }

If it can't handle the exception (I don't have a butler), then the best thing is to just let the exception percolate up to the calling code to either handle or throw, that is:
    public void makeTea() throws ElectricityCutOffException {
        teaPot.prepare();
        kettle.boil();
        kettle.pourContentsInto(teaPot);
    }

Now calling code has to either handle or throw the exception.

Do NOT declare an exception that a method does not throw


If you declare that a method throws a checked exception that it cannot actually throw, then you are condemning callers to having to handle or throw an exception that cannot happen - percolating unnecessary try/catch code around the system. Don't do it.

For a method which implements or overrides a method of an interface or superclass which declares that it throws an exception, do not make it also declare that it throws that exception unless it actually does.

Unchecked exceptions and more

I have recently read "Clean Code" - I really like the first chapter - worth buying just for that. There is a chapter on exceptions, in which Michael Feathers writes about the use of unchecked exceptions and other things. I'm not going to write more myself - buy "Clean Code" instead.

If you are too cheap to buy "Clean Code" or have read it and want a different opinion, then read my "programming in the small" articles which cover some of the same ground (in some cases better, in some cases worse, and not a complete intersection of topics - in particular there is more stuff covered
in "Clean Code").

Copyright © 2008 Ivan Moore

6 comments:

Andy said...

I'm waiting for Amazon to send through a copy of Clean Code... they're taking some time about it...

This is my take on checked vs. unchecked exceptions

David Peterson said...

Nice example, though I'm wondering if ElectricityCutOffException might be a bit too implementation-specific to be thrown by makeTea()?

Chris said...

Yeah, I agree with David. I think it might make sense to declare makeTea() as throwing a CannotBoilWaterException or similar.

Paul Simmons said...

Nice article Ivan, full of subtleties one of which I think need expansion:

kettle.pourContentsInto(teaPot);

is a nice example of encapsulation, could so easily have been a messy pair of get/setters, something like:

teapot.fill( kettle.getContents() );

exposing unnecessarily the contents of the kettle and thus limiting future capabilities of kettle, and with potential risk to its use in threaded scenarios.

And of course the use of the verb percolate for which we should consider whether your blog is a contender for the PG tips award for "outstanding contributions to the world of tea drinking" ( see http://www.nicecupofteaandasitdown.com/ )

Str8y said...

Your original PITS article is no longer available from truemesh.com (or even google cache).
If you have a copy anywhere, please could you repost it.

ta lots.

Ivan Moore said...

Hi Str8y - my original PITS articles are available at https://web.archive.org/web/20150415132201/http://ivan.truemesh.com/archives/cat_programming_in_the_small.html (I've edited the post to use this link too)