Why you should check method parameters for validity
I was reading one tip from Effective Java today, item 23 check method parameters for validity. It was talking about why you should check method parameters for validity. This is often something which you can forget about because you are usually using the class and method yourself and when testing the code you pass in a correct value. Perhaps if you are unit testing you pass in some unusual values, given some confidence that you method has passed the other expected value tests.
This is a classic Effective Java tip, very simple but yet very .... yes I can't resist it Effective.
Implementing this tip and checking methods parameters for validity would help to eradicate one of the classic programmer/developer blind spots and probably the main reason for QA teams. Before you get angry with my preaching, I too have been guilty of this. When developers test their own code they often get into a kind of groove and only pass in a few different valued variables. They usually test something some many times they keep putting in the same value over and over until the code finally passes this test.
If we were writing a (as it's a boiling heat wave in Birmingham) method which converts Fahrenheit to degrees then the developer would pass in a few number 21, 10, 90 and usually write some code with just one of those value say 50 and keep testing the code with this until it works. After that a few different positive numbers, bingo the method is tested, give it the rubber stamp. The example I am using is without unit test code which was the way I used to work (before I had an epiphany and saw the light ).
Without checking for validity you are underestimating the sheer stupidness of the users. There is obviously the argument that you make your code idiot proof they will go and create an even greater idiot but we will leave that. Users love doing stupid things, sometimes to see if they can break it !!!!! It would be long before a user/customer would put in a negative number or perhaps even 1 million (dollars MWHAHHAA - doctor evil laugh) and then they would complain it wasn't working.
Of course the real nightmare scenario is that you would put in a dodgy/invalid value but this would only show up as an error ten classes down the road, leaving you with a puzzling bug hunt and some slow debugging back up to the method that has caused the error.
By checking the methods parameters for validity you can throw up an error as soon as possible so as to stop any more code running when you know it wouldn't work with the values passed in.
It also makes sense to test for validity inside the method because it keeps the logic all in one place and can be then the validity checking code is not repeated by all the classes that use this method, keeping your code nice and DRY (Don't Repeat Yourself).
Usually you can test for values being positive, not null, certain values and then use the @throw tag to document the restrictions to this method. Popular exceptions to throw are illegalArguementException, NullPointerException and indexOutOfBounds, this exceptions tend to do exactly what they say on the tin and anyone using your class will know what to expect.
There are some occasions that you can't check for validity but most cases you can probably validate the parameters passed in and this small amount of work will hopefully stop any bugs occurring inside or from using the method. I have found that I have been validating the parameters more now that I have been writing more unit tests. When I am writing a unit test I think more about the restrictions I should place on the parameters values
This is a classic Effective Java tip, very simple but yet very .... yes I can't resist it Effective.
Implementing this tip and checking methods parameters for validity would help to eradicate one of the classic programmer/developer blind spots and probably the main reason for QA teams. Before you get angry with my preaching, I too have been guilty of this. When developers test their own code they often get into a kind of groove and only pass in a few different valued variables. They usually test something some many times they keep putting in the same value over and over until the code finally passes this test.
If we were writing a (as it's a boiling heat wave in Birmingham) method which converts Fahrenheit to degrees then the developer would pass in a few number 21, 10, 90 and usually write some code with just one of those value say 50 and keep testing the code with this until it works. After that a few different positive numbers, bingo the method is tested, give it the rubber stamp. The example I am using is without unit test code which was the way I used to work (before I had an epiphany and saw the light ).
Without checking for validity you are underestimating the sheer stupidness of the users. There is obviously the argument that you make your code idiot proof they will go and create an even greater idiot but we will leave that. Users love doing stupid things, sometimes to see if they can break it !!!!! It would be long before a user/customer would put in a negative number or perhaps even 1 million (dollars MWHAHHAA - doctor evil laugh) and then they would complain it wasn't working.
Of course the real nightmare scenario is that you would put in a dodgy/invalid value but this would only show up as an error ten classes down the road, leaving you with a puzzling bug hunt and some slow debugging back up to the method that has caused the error.
By checking the methods parameters for validity you can throw up an error as soon as possible so as to stop any more code running when you know it wouldn't work with the values passed in.
It also makes sense to test for validity inside the method because it keeps the logic all in one place and can be then the validity checking code is not repeated by all the classes that use this method, keeping your code nice and DRY (Don't Repeat Yourself).
Usually you can test for values being positive, not null, certain values and then use the @throw tag to document the restrictions to this method. Popular exceptions to throw are illegalArguementException, NullPointerException and indexOutOfBounds, this exceptions tend to do exactly what they say on the tin and anyone using your class will know what to expect.
There are some occasions that you can't check for validity but most cases you can probably validate the parameters passed in and this small amount of work will hopefully stop any bugs occurring inside or from using the method. I have found that I have been validating the parameters more now that I have been writing more unit tests. When I am writing a unit test I think more about the restrictions I should place on the parameters values
4 Comments:
Hi,
If there is one strong case for validating method arguments (including constructor arguments), it is that incorrect values could put your object in an invalid state. For example, for an Account object, a null username will result in a false assertion, and an exception should be raised.
Efficient exception handling has been a pet peeve of mine for a very long time, and I have collected various resources and written several blog entries on the topic. If you are interested, please read my latest post on exception handling.
By Anonymous, at Thu Jul 20, 03:35:00 pm 2006
It's hard to disagree with a "motherhood and apple pie" issue without people getting all defensive about it. But the recommended approach is overly simplistic.
There are many times where testing a parameter is just a waste of time and one more chance to introduce a bug - especially if there's no conceivable way that the parameter can be bad. There are other times where testing a parameter is conceptually valid but the only way that the parameter could be wrong is due to a coding error, and if it's wrong then you'll get an exception when you try to use the parameter anyway (NullPointerException being the big case of this). There are times when testing a parameter for programmer screw-ups is necessary lest really obscure exceptions or results happen or, even worse, the code gets confused and trashes a database or something. There are times when testing a parameter is necessary because the user can provide incorrect input and needs a clear explanation of how to correct the mistake.
You really need to consider a number of things when pondering parameter testing.
o Why is that parameter value a problem? Is it just that you didn't want to include code for that case? Is it because the request makes no sense? Is it because there's a business rule against it?
o How could the invalid value arise? Is there no conceivable way it could happen, leaving only the totally unexpected? Is it only possible through programmer screw-up? Environment misconfiguration? Garbled data over a communications link? Defective pre-existing persisted data? Improper user request?
o Who's going to have to deal with the problem? Is it a coding issue that's going to come back to you, the developer? Is it something that the calling code should deal with, like doing something different or initiating a retry? Is it something that's going to be handled by your computer operations staff? Is it something that an upstream data provider needs to fix? Is it something that your DBAs are going to need to deal with? Does the user need to be told that he's made an invalid request?
o What will happen if no test is made? Will the code quickly give an equivalent error? Will it do something confusing or harmful?
o In light of who's going to deal with it, what information do you need to include in order for them to be able to figure out what went wrong and how to fix it?
Bertrand Meyer notes that a lot of what's called "defensive programming" is more like "paranoid programming". It's blindly testing everything everywhere all of the time over and over again just in case because you never know and maybe things could go wrong even if you don't know how and then where would you be because you don't really understand what you're doing and OMFG! :-)
Know what your business rules are, and be sure that they are always enforced. Know what your coding contracts are, and assure yourself that they will always be met—this can involve parameter testing in some cases but simple inspection in others.
By Doug, at Thu Jul 20, 05:44:00 pm 2006
Thanks for the comments. As usual your comments Doug are spot on and very thought provoking.
It follows a trend when you post a comment, I come from one angle, you comment with valid points based on academic reading and experience and I get both sides of the arguement.
You are right, you don't need to always validate methods. I think it depends on where you are getting the information from, if it is coming from the front line and customers are inputting values then I think it is wise to test for validity of the parameters.
What you should do with them of course can be a tricky subject but you probably can't too far with the code
By The Hosk, at Thu Jul 20, 10:59:00 pm 2006
hosky,
I really like your blog. You show us your ideas, your opinions and many things, something I never think before.
About this problem, check these
+ @Nullable/@Notnull: http://www.jetbrains.com/idea/documentation/howto.html
+ Wrox's Beginning Algorithms: The authors recommend to check validatiy by using assert
+ Support For ‘Design by Contract’, beyond “a simple assertion facility”: http://www.oreillynet.com/onjava/blog/2006/07/touring_the_top_10_rfes.html
By t800t8, at Sat Jul 22, 09:50:00 am 2006
Post a Comment
<< Home