Too many programmers don’t understand exceptions. Do you?

I am still amazed to see how many (even seasoned) Delphi programmer don’t understand exceptions. This post starts from a nice video posted by the Silver Coder.

He states that exceptions are not the best idea and the reason mentioned in the short video is that try/except makes the code slow and difficult to read. This is true, but there are much deeper mysteries around Try/Except. The main reason is a programming rule that states that you should never swallow exceptions!

His example was like this:

program Example;
var x,y: integer;
begin 
  x:= 10;
  y:= 0;
  try
    x := x div y;
    Writeln('x = ', x);
  except
    on e: exception do WriteLn( 'exception: bla bla bla');
  end;
end;

My question would be what would you do if you have a routine that receives a zero as parameter? Replace zero with one? Don’t do the calculation? Show an error msg like “press yes to do the calculation anyway”? (What if you are in a console program? What if you don’t want to halt the program?)

Since that example is definitively unrealistic, let’s turn it into a more realistic piece of code:

program SplitCandies(CandyPieces, Kids: integer): integer;
begin 
try
  Result := CandyPieces div Kids;
except
  Result:= ?; // ha ha ha, gotcha!
end; 
end;

As we can see, letting a routine to continue (returning a fake result) after an exception IS NOT FINE! We don’t know how to recover if y = 0, therefore we cannot return a valid value.

What is the correct way to handle this? The Silver Coder suggests defensive programming – checking for zero inside the function. Let’s see this, again, in a more realistic scenario:

program SplitCandies(CandyPieces, Kids: integer): integer;
begin
  if Kids > 0                           // Defensive condition
  then Result:= CandyPieces div Kids
  else Result := ?;                     // Still gotcha!
end;

The above function is almost fine. So, let’s make it better. There! We fixed it:

program SplitCandies(CandyPieces, Kids: integer): integer;
begin 
  Result := CandyPieces div Kids;
end;

But you might say: But Gabriel, your function will crash if you have zero kids at the party. YES. Let the program crash and send a bug report (I hope you use madShi to generate bug reports). Get the bug report and and fix the code that is sending you a zero. There is where your problem resides!

program Party
begin
  if PartyStarted
  AND (KidCount > 0)                      <------ here was your problem
  then SplitCandies(100, KidCount)
  else ShowMessage('No kids at your birthday? You need some friends!');
end;

Problem fixed! No exception swallowing forced down on our throat.


Note: There are justified cases where you can use try/except but these are EXTREMELY rare. I have 700000 lines of personal code and I barely use it.

The justified cases are:

  1. When you know how to recover from the exception.
    In most cases you don’t.
  2. Driver, service and server apps that are not allowed to crash.
    But this is not an excuse to swallow the exceptions. You should log the exceptions to a file.
    But then you should have zero exceptions logged, and you should check that log at least once per day. Otherwise, it is not different than swallowing the exceptions.
  3. You expect an error to occur.
    For example when I process large number of images at batch, I ignore the Jpeg that are corrupted. But in this cases I trap ONLY the Jpeg-related errors, not all eceptions.

If anyone has a different example where try/except is fine, let us know (code example please).

Also note that “zero division” behaves differently for integer and real numbers. More exactly there are two different exceptions: EZeroDivide (for floats) and EDivByZero (for ints).


If you are still unconvinced, a big chapter in my book is dedicated to exceptions. Take a look!

Leave a Comment

Scroll to Top