Sunday, July 24, 2005

Debug.Assert(this.WillNotHappenInProduction)

You couldn't wish for a simpler tool: just stuff a conditional test in your code to document what should be true at that point, and the debug build of your app will throw up a message if you (well, obviously not you; some other developer) got it wrong and didn't satisfy the precondition or screwed up some data somewhere.


But what should your code do if the assert is untrue in the release build? Well, you say, that shouldn't happen because your testing will have uncovered all the bugs that would lead to the assert failing. Hah!


In the best traditions of defensive programming, what you should really do is abort at least that operation by throwing an exception. But if you're going to do that, why bother with the assert in the first place?


The only justification I can think of that isn't pure "my code ain't got bugs" optimism (and if you're that kind of programmer you won't be bothering with asserts), is that you're sure that testing is going to exercise the dubious condition and you really can't afford the enormous time and space penalties of the if not condition then throw exception statement.


Don't get me wrong, I love Debug.Assert; it's a neat way of expressing pre- and post-conditions. But too often after writing one I get this nagging feeling that I haven't done enough to make my code "good". Perhaps what I need is a Release.Assert statement instead.

1 comment:

Shannon Wagner said...

For me, Debug.Assert has caused more problems than it has solved. As a beginning programmer, I read all the advice to assert assumptions (and attended John Robbins' lecture on the topic), so I used the assertion technique liberally.

A few months later when my first production server application crashed due to an unexpected input, and the assertion fired, we ended up with a hung process on the server until someone logged on and closed the assertion dialog. Troubleshooting the issue was confusing, to say the least.

You may say we shouldn't have deployed a debug build. Maybe, but we had reasons for doing so, and that actually wasn't what caused our problem. Even if we had deployed a release build, then the application would have just blindly charged past the error condition (unless I also threw an exception, but then what would be the point of the assertion in the first place?).

You may say that the asserted condition should never happen in production code. Well, it did. More than once.

My advice, based on my experience so far - use exceptions, and use them liberally, but never use an assertion. Even better if you can get into a habit of good unit test coverage, but I am still having trouble developing that habit myself.