Use Assertions to Prevent the Impossible

Whenever you find yourself thinking "but of course that could never happen," add code to check it. The easiest way to do this is with assertions. In most C and C++ implementations, you'll find some form of assert or _assert macro that checks a Boolean condition. These macros can be invaluable. If a pointer passed in to your procedure should never be NULL, then check for it:

void writeString(char *string) {
  assert(string != NULL);

Assertions are also useful checks on an algorithm's operation. Maybe you've written a clever sort algorithm. Check that it works:

for (int i = 0; i < num_entries-1; i++) {
  assert(sorted[i] <= sorted[i+i]);

Of course, the condition passed to an assertion should not have a side effect. Also remember that assertions may be turned off at compile time—never put code that must be executed into an assert.

Don't use assertions in place of real error handling. Assertions check for things that should never happen: you don't want to be writing code such as

printf("Enter 'Y' or 'N': ");
ch = getchar();
assert((ch == 'Y') || (ch == 'N')); /* bad idea! */

And just because the supplied assert macros call exit when an assertion fails, there's no reason why versions you write should. If you need to free resources, have an assertion failure generate an exception, longjmp to an exit point, or call an error handler. Just make sure the code you execute in those dying milliseconds doesn't rely on the information that triggered the assertion failure in the first place.

Assertions validate your assumptions. Use them to protect your code from an uncertain world.

The Pragmatic Programmer: From Journeyman to Master

— by Andrew Hunt and David Thomas