A Funny Java Flavoured Look at the World

Monday, May 22, 2006

How should you deal with null's passed into methods

another day, another bug put in the system which has halted what ever development I was doing. This is a classic case of putting a fix into solve one problem and in it's place is one if not more bugs.

This is a slightly interesting bug. Basically we have a Utils Static/helper class and it has a removeFraction function. The function itself is pretty dodgy but basically you pass a String into the function but you know the String is really a number but as a String. This isn't to bad because a lot of variables are passed around as String or a good example is that the main method in Java accepts an array of String but the variables could be anything waiting for you to convert them.

The function then finds the index of the "." fullstop and then takes what's on the left (no rounding here). Although it's a tad dodgy it's not to bad .......Except when you pass a null into it. Now it is difficult sometimes to know what to do if some code tries to pass a null into your method, a lot of the time you could just say, well if you are stupid enough to pass me a null I am going to throw an exception and this is fair play at least you are warning code that calls your function what you might do. I thought of catching the null and passing it back as null but then this is not a good thing to do and more than likely you are just passing the bug on, unless the class you are passing back to has better exception handling.

I was disappointed that this problem had occurred because for this class I had created a unit test, so the developer added this method he could have easily added in a test. A good reason why you should add unit tests (along with all the others) is that when you are testing a function/method when you think about how you should test the function you often think about what should happen if some fool passes in a null but often when you don't write a unit test you never think that anyone would pass in a null, why would they do that.

I have read in effective Java and by a presentation on API both by Joshua Bloch that you should validate the values passed into a method and I think this is a prime example. By validating and dealing with wrong values and nulls inside the method it means that you will only have to have this code in once instead of all the code calling the method having to validate it.

In this example I have chosen to put a try and catch block around the code which tries to remove the fullstop, so if it is a null an error gets thrown and I have decided to return a zero which seems a fair trade a null for a zero. The one problem I did have was I wasn't quite sure where this badboy got called and the effect returning zeros might have. I have tested it and all seems to be working but you never can tell.

7 Comments:

  • The problem with validating things inside the method is that it probably has no idea what to do when it finds something wrong. The method is missing the context. Most of the time, it's really the caller who knows how to deal with the problem.

    After all, if all that you wanted was an exception that'll bring the system to a sudden halt, the NullPointerException is already doing that for you :-)

    Covering up unexpected data—returning zero for a null, for example—is not usually a good practice. Yeah, sometimes you can't avoid it. And sometimes you need to get a system back up and running quickly and sweeping the problem under the rug is the best way to make that happen. But most of the time it's best to confront the problem and deal with it.

    By Blogger Doug, at Tue May 23, 12:18:00 am 2006  

  • I totally agree with your point and that for most cases I would throw an error and let the caller decide what they would like to do because like you say they can plan how to deal with an exception and passing back a zero can definitly be hiding the problem.

    In this case I wasn't sure what the calling code would like to do but I was sure that they weren't expecting to pass a null and certainly wasn't prepared to handle one (well the same developer wrote both parts).

    It did raise an interesting question which was what should you do with null's in your method. I think in most cases I would probably throw them back out because if all methods internally delt with nulls then that would be a lot of extra coding for not much value. Also in a lot of cases there isn't an obvious answer what would be the best practise of dealing with a null and your default might not be what the caller would be expecting and that would be a very tricky bug to find indeed.

    thanks for you comments Doug, as usual they are very insightful

    By Blogger The Hosk, at Tue May 23, 01:40:00 am 2006  

  • Hey, you're unnecessarily complicating the situation. Throw an exception. Okay if the user is not really expecting to pass a null - this is an exceptional condition, and he's expected to deal with this as an exceptional condition. Any other alternative would have other caveats. Keep you own class simple.

    By Anonymous Anonymous, at Tue May 23, 03:48:00 am 2006  

  • bad idea to pass back 0 when null is passed in. This is the same result as when someone passes in "0.75". You should thow a BadArgumentException. This is exactly what it is.

    By Anonymous Anonymous, at Tue May 23, 12:02:00 pm 2006  

  • Definitely throw an exception. Even let it throw the NullPointerException. Shortest and clearest code with meaningful and proper behavior. Most other people should also have non-null values.

    Only high up the pipe with sketchy data should you even need to worry about checking if it's null or not.

    If you give non-exceptional results (such as "0") for exceptional circumstances, you'll forget what it does and get bugs later.

    By Anonymous Anonymous, at Tue May 23, 07:44:00 pm 2006  

  • Thanks for your comments guys I think you have made very good points and have persuaded me to go back in there and sort it out.

    The only problem I have is find out how many methods call this function and hope that it isn't too many.

    I am back on the path of good programming.

    By Blogger The Hosk, at Tue May 23, 11:12:00 pm 2006  

  • Use the @NotNull and @Nullable annotations from JetBrains and you will not have to worry about this:

    public @NotNull String removeFraction(NotNull String fractionalText) { ... }

    if you write:

    String s = removeFraction(null);

    then the IDE will warn you that you are doing something wrong. It will do this in almost every case where it is not guarenteed that the argument to removeFraction is non-null.

    By Anonymous Anonymous, at Wed May 24, 06:01:00 am 2006  

Post a Comment

<< Home