Thursday, November 13, 2008

Assertions and Errors

Out of any context, do those two words in the title of this post mean the same? I mean, is there any way in which those two things (assertions and errors) could be considered semantically equivalent? I would think not, but apparently many programmers think otherwise.

Java is a great programming language. It's a language that allows programmers to explicitly state error or "exceptional" conditions. Recently this language was extended with a feature that allows programmers to express intent explicitly: assertions. This is a great feature, because the assertions can be checked at runtime, so that the programmers assumptions are tested under operating conditions, aside from also serving as a form of documentation, making programming cleaner and more methodical.

As I just said, Java assertions are great, the problem comes when they are abused. Some programmers use them to "state errors", that is, to do the things that the exception and error mechanism of Java should do. Assertions should be used to express the conditions under which the program should operate, not error conditions! And so you find things in Java code like:

assert false;

which basically states an error state has been reached. I can't even start to explain why this is in so many ways wrong, but let us start with the obvious. What the heck does "assert false" mean? You are asserting 'false'. You are saying 'false' is 'true'. That doesn't mean anything! Whenever this line is reached, all you will be left with is a message saying the Universe will cease to exist tomorrow. It tells you nothing.

Now let's go with the practical problems. Since assertions are not meant to state errors, but just intent of normal operating conditions, their checking is optional. That is, to check them at runtime you have to enable assertion checking. This is something you do during production, but not on deployment. So basically, during actual operation, these assertions won't be checked. Which means that, if you use assertions as above, the errors won't be caught, and will just propagate through the system producing unpredictable, unstable system states. This just happened to me. I was using some code from someone with this bad habit, and I had not enabled assertions. So, the program ran 'fine' all the way through without apparent problem. Then, I enabled assertions to check some of my own assertions, and everything started breaking all over. A lot of 'assert false' assertions started popping, which means that the program wasn't actually running properly, and the results I was gathering before were probably incorrect. But before I enabled assertions, there was no sign of error conditions in the program!

If you are a programmer and reading this, please do not do this. If there is an error condition, then state it as an error, instead of asserting that 'false' is 'true', throw an error:

throw new Error("Error message");

see how easy that is? You will do yourself and those who use your code a big favor. Learn to understand the difference between errors and assertions!