Skip to content

Asserts are Awesome (and Exceptions certaintly don’t replace them)

September 5, 2012

Assert vs Exception

That actually is a quite common rant and it is usually won by exception. Even Jon Skeet thinks that assert could be replaced entirely by exception. Many people will read his opinion and just fallow it and that is unfortunate. I wish everyone would use assertions more. As I see them, they have completely different purpose from exceptions.

No Room for Assert?

First lets think of why people think assert can be replaced by exception. At first glance I need an assert to check if program is not in unexpected state.

For example, we expect that some argument will not be nullptr:

void myFunction(ImportantType* importantVariable)
{
   assert(importantVariable != nullptr);
   ...
}

or some function returns not nullptr

void myFunction()
{
   ...
   ImportantType* importantVariable = someImportantFunction();
   assert(importantVariable != nullptr);
   ...
}

or our result is valid

ImportantType* myFunction()
{
   ...
  assert(resultIsCorrect(someResult));
  return someResult;
}

But isn’t that risky? Using or returning value that we know is not correct? It might very well screw up other calculations and that will lead to many more problems. The best we can do here is stop execution before something worse happens and go to safety where we know what to do. This sounds like a job for exception. Isn’t it better to just throw rather than try to work with something we were not expecting?

After all doesn’t assertion mean “this shouldn’t have happened”? Seems like there is no room for assert…

Not a Chance! Asserts are Awesome!

OK, so where is assert better than exception? Well there are cases when I could not live without assert and exceptions just wouldn’t do the trick. And that is in private methods.

Lets take the simplest example possible. In public method if I can’t find a file, I should throw, but that shouldn’t always be the case with private methods, for example in some cases I could assume that file is empty. Where can I do it? Well, if everywhere where I use this private method, I wrap it in try catch, just to work like nothing has been done, I can very well do the same in the private method. Without exception swallowing information that something indeed went wrong.

Suppose you have some archives you want to load to your application. Some lines of it might be corrupt or even entire archive. So we need to take care of this, we don’t want to let some unpredictable data to enter our application. But we also don’t want application to crash just because it didn’t get some semi-important data. (Lets say we’re loading road network, if some of roads are corrupt it is better just to skip them, it’s not worth killing entire application or data load process, neither it is logical to add them if we know they will contain corrupt data) So, the code could look like this:

for (std::vector<std::string>::const_iterator it = files.begin(); it != files.end(); ++it)
{
   try
   {
      DataFile dataFile = OpenFile(*it);
      for (dataRow jt = dataFile.dataRowsBegin(); jt != dataFile.dataRowsEnd(); ++jt)
      {
         try
         {
            addData(*jt);
         }
         catch(Exception ex)
         {
            //something is wrong with data line... log something...
         }
      }
   }
   catch(Exception ex)
   {
      //something is wrong with the file... log something or do something else
   }
}

Well that sure looks ugly… We can move inner loop to another function, but just having try catch blocks inside a loop doesn’t look so well.

Another problem with it is that we might never notice that something is wrong in the first place unless we read logs and I don’t know anyone that looks at them unless something wrong happened. So it looks like we finally have somewhere to use assert — we can place it inside catch blocks, this way user wont be interrupted but on debug mode we will see that something did not go as expected right away!

But why do we need exceptions in the first place? We can simply assert inside local functions and declare a contract, that for corrupt file, it will log and then return empty dataFile and for corrupt line it will log and  just return.

Bottom Line

Don”t overlook assertions. They can help you spot bugs in your software much easier than exceptions. For me answer whether use exception or assert looks like this:

  • In public methods exception wins. But I still place them to check arguments just that developer using my class (most likely it’s me) would be informed that he is doing something he is not supposed to.
  • In private methods assert wins. Not all the time of course, but there is nothing I hate more than swallowed exceptions. All they do is hide bugs, while assert pops them out directly to your face.
No comments yet

Leave a comment