One of the hallmarks of modern programming languages is structured exception handling. Put simply, exception handling is a way for programs to handle “exceptions” to expected behavior. An error occurs, and it rockets up the call stack until code that knows what to do with it “catches” it. If it’s left uncaught, the program shows a big ugly error message to the user and exits. This reduces cross-cutting concerns by allowing application logic to separate cleanly from exception-handling logic.
It seems a shame to reserve such a powerful mechanism for error handling, which (if all goes well) should occur very infrequently. Following the Extreme Programming mantra that if a programming practice is good, more of it is better, I set out to build a simple application that, far from using exception handling for such edge cases, throws and catches exceptions whenever things are working properly, and reserves the antiquated notion of “return values” and “successful function calls” for their rightful place – indicating error conditions. I call such an approach Exception-Based Programming, or EBP, and it is the future. The example that follows is written in C#, but it translates easily to any modern language.
Consider a simple app that adds integers together but requires a password to prevent unauthorized use of such a valuable service. The traditional approach might be to write a function like so:
public int AddIntegers(string secretPassword, int firstInt, int secondInt)
{
if (!IsAuthorized(secretPassword))
throw new System.Security.SecurityException("Your password is not correct!");
return firstInt + secondInt;
}
private bool IsAuthorized(string secretPassword)
{
return _passHash == secretPassword.GetHashCode();
}
Here’s essentially the same code, greatly simplified by the conversion to Exception-Based Programming:
public string AddIntegers(string secretPassword, int firstInt, int secondInt)
{
try
{
string errorMessage = IsAuthorized(secretPassword);
return errorMessage;
}
catch (BooleanTrueException)
{
Console.WriteLine("Password is correct. Adding {0} to {1} and throwing result", firstInt, secondInt);
SuccessException results = new SuccessException("Here's your result");
results.Data["value"] = firstInt + secondInt;
throw results;
}
catch (BooleanFalseException)
{
return "Your password is not correct!";
}
}
private string IsAuthorized(string secretPassword)
{
if (_passHash == secretPassword.GetHashCode())
throw new BooleanTrueException();
else
throw new BooleanFalseException();
}
See how much more legible that is? (The class definitions for BooleanTrueException, BooleanFalseException, and SuccessException are available in the full code download accompanying this article.)
The client code is even simpler. Here’s the old way:
private static void AddIntegersTraditional(TraditionalClass traditionalClass, string password, int firstInt, int secondInt)
{
Console.WriteLine("Result is {0}.", traditionalClass.AddIntegers(password, firstInt, secondInt));
}
And here’s the EBP way:
private static void AddIntegersEBP(EBPDemoClass ebpDemoClass, string password, int firstInt, int secondInt)
{
try
{
string errorMessage = ebpDemoClass.AddIntegers(password, firstInt, secondInt);
Console.Error.WriteLine("ERROR: " + errorMessage);
return;
}
catch (SuccessException results)
{
Console.WriteLine("Result is {0}. Success message is '{1}'", results.Data["value"], results.Message);
}
}
I wrote a simple console app to run and benchmark the EBP approach first and the traditional approach second. It calls AddIntegers with the correct password, then tries again with the wrong password to confirm that security is working:
Note that the EBP code is spared the public humiliation of that unhandled security exception, since exceptions are now fully expected.
The EBP approach works for any problem domain. Need to retrieve rows from a database? Throw them back! Exceptions work like any other .NET object and can be bound to controls, placed in collections, enumerated, and more. The only limit is your imagination. Oh, and CPU power, because exceptions are really really slow due to the enormous overhead of exception processing. This should only be a temporary problem, though.
By merely rewriting your app from scratch, adding lots more code, and accepting a six-fold drop in performance , it’s possible to unlock the power of EBP in your own code. Based on the user experience alone, I’m pretty sure Eclipse is already written using it.
Chris D Said:
“Based on the user experience alone, I’m pretty sure Eclipse is already written using it.”
Buuuuurrrrrrrnnnn!!! :P
Architect Said:
This is probably one of the most ridiculous articles I ever read.
You write:
It seems a shame to reserve such a powerful mechanism for error handling, which (if all goes well)
I assume you haven’t heard about If-Else Statements yet.
Joel Potischman Said:
Um, note the publication date.
Grey Said:
I got linked to this without seeing the date, got halfway through and was thinking “This is f*****g retarded, but arc90 seems to have some really cool stuff, Is this a joke or something?!” Checked the date, oh… OOHHHHHH.
You got me Arc90, You got me.
Good one, Even if I’m a bit late in finding it :)
Dan Vail Said:
Wow. I started to read this and thought “this guy is a total retard” and then the comments led me to the date. Nice job man, this made my laugh hard…