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 is a reply to the Silver Coder’s video.

He states that exceptions are not the best idea and the reason mentioned in the (way too) short video is that try/except makes the code slow and difficult to read.

I respectfully disagree with his statement, but for a totally reasons than the ones he listed. The correct reason is 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 his 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).


If you are still unconvinced, I dedicated a full chapter in my book to exceptions.

Leave a Comment

Scroll to Top