Abstracting Away From Exceptions 18
I’ve been unsatisfied with exceptions for a long time. Sure, I use them and find them helpful, but I feel that they are a bit of a cop-out as a language construct. If an exception could talk, it would say “get me the hell out of here.” And, you have to admit, that’s a bit rude.
Exceptions seem to encourage “controlled abort” as an error handling policy. You throw an exception, it travels up the stack, and you catch it someplace else. All of your work is unwound (you hope) and then you are left with the task of logging the error or trying something else.
It is true – in many applications you do want to “fail fast” but not all applications are the same. Sometimes, you do want to go on, and it would be nice if exceptions had transactional semantics – it would be nice to have a guarantee that your program is in the same state it was before your try, in all of the ways that are important to you. Without that guarantee, programs devolve. “Log and fail” looks like the only option.
In this blog, I’m going to describe a first step toward rationalizing error handling in applications with pervasive exceptions. It’s a simple one, and now that I think about it, it probably doesn’t deserve all of the build up that I just gave it, but I suspect that I’ll be writing more about this topic. There’s definitely more to discuss.
A few days, I ago I tweeted that I was looking at condition systems for error handling. I was inspired by the fact that Ola Bini decided to add a condition system to his new language: Ioke. As far as I can tell, condition systems were first developed in Lisp. If I had to characterize the difference between an exception handling system and a condition system it would be that instead of saying “hey, get me the hell out of here”, a condition system says “I don’t know how to handle this, did you register something which could help?” All in all, it looks like a more reasonable approach.
After I tweeted this, Tracy Harms tweeted that the J Programming Language has a function called adverse which could be used as a the basis for a condition system. What does adverse do? Well as it turns out, it is very simple. Here’s a translation to C#:
public static class Adverse<T>
{
public delegate T Function();
public delegate T RecoveryFunction();
public static T Call(Function attemptFunction,
RecoveryFunction recoveryFunction)
{
try { return attemptFunction(); }
catch (Exception e) { return recoveryFunction(); }
}
}
Adverse accepts two functions. It calls the first and returns its value. However, if there is any kind of an error, it calls the second function and returns its value instead.
This might not look like a big deal. Superficially, it looks like another way to swallow exceptions. But, you can (of course) write an adverse which passes the caught exception to the second function. You can also write an adverse which works for void functions:
public static class Adverse
{
public delegate void Procedure();
public delegate void RecoveryProcedure(Exception e);
public static void Call(Procedure attempt,
RecoveryProcedure recovery)
{
try { attempt(); }
catch (Exception e) { recovery(e); }
}
}
How is adverse better than straight exception handling? Well, first of all, it forces us to separate responsibilities. And, in general, that’s good.
A long time ago, Bertrand Meyer described something called the Command/Query Separation Principle. The idea was that methods should either change something or return something back – they shouldn’t do both. The funny thing about exceptions is that they can do both and as a result we rarely think about structuring exceptions around the distinct actions of getting something or modifying something. And, that’s a shame. There are often cases where we are obliged to return something and it’s better that we return some sort of a Null Object rather than a null. In other cases, we need to focus our attention on what we need to do to patch up the state of our application. I suspect Adverse can help with that. There’s nothing that forces attention like the syntactic need to write some piece of code to use a construct.
I’ll end with some toy examples of Adverse in use (I haven’t put it through real paces yet):
string line = Adverse<string>.Call(GetLine, e => "");
string line2 = Adverse<string>.Call(GetLine,
e => { LogError(new ReadError(e));
return "";});
Adverse.Call(SomeWriteOperation,
e => LogError(new WriteError(e));
I’ve used lambdas here to be brief, but imagine plugging in your own handler function. You could start to parameterize your code with error handling policies. It could be interesting.

The major Lisp and Smalltalk dialects support handling a fault at the location of the fault and retrying, or handling at the location of the catch and continuing from there. Java’s catch-only limitation has been a continuing surprise.
“Adverse” in Java would still have this limitation. The recovery capability can only take over at the point of the corresponding catch, and so loses the lexical environment in existence at the point of the fault.
Patrick, thanks. I’ve been playing with the idea of how to approach those sorts of things at the library level in Java and syntactically, it seems to get very weird. Seems like it would be much easier to do something like a condition system in Ruby (provided it hasn’t been done already), given the fact that you can monkey patch it in.
An Erlang expert I know once said to me that the Erlang philosophy is to just throw the process away and start over. Since there are gazillions of processes in a typical Erlang app., this works pretty well. Customers are used to dropped calls, anyway ;)
Of course, that strategy would not work in all situations, but it’s an interesting Zen-like solution. We sweat over how to keep the process running, when maybe we should step back and ask ourselves if we should just “let it fail” instead and start over.
I’m not a fan of exceptions. Exceptions want to be messages like any other IMHO. Instead they are locked in tiny try/catch jails. In a distributed system this is a easier to see (or ignore as @Dean mentions). Your Adverse example heads in the message direction but still looks like things are coupled kind of tight. What would a series of retries look like? Thanks for writing about this.
Note that functions which do not take any arguments are not functions in the mathematical sense (unless they produce a constant result, which is not very interesting).
In the case of adverse, I think your fallback function should get the same argument(s) that were passed to the function that blew up.
And I think that you are right that this should not be that big of a deal—mostly because in most cases you should not need this kind of mechanism. Conceptually speaking, exceptions should only be used in exceptional contexts.
Interesting approach. This reminds me of “causalities” in the CCR (concurrency and coordination runtime) and the ability to post either a successful result or an exception to a port, specifying different methods to execute depending on the result.
The J operator :: (adverse) does what rdm expects. It takes as its parameters two functions, each of which takes at least one argument. If the first function fails the fallback function is called with the same argument(s).
Michael, I find this intriguing… given that I’ve never even seen J source code.
I have an idea on improving the Adverse implementation with regards to functions. You can move the T generic parameter from the class to the Call method. This way, you can take advantage of C#’s type inference and remove the Adverse ugliness:
public static class Adverse { public static T Call<T>(Func<T> attemptFunction, Func<Exception, T> recoveryFunction) { try { return attemptFunction(); } catch (Exception e) { return recoveryFunction(e); } } }and the client code:
string line = Adverse.Call(GetLine, e => ""); Console.WriteLine(line); string line2 = Adverse.Call(GetLineError, e => { LogError(new ReadError(e)); return "Got error!"; }); Console.WriteLine(line2);Oops! I meant “the Adverse<string> ugliness”
Michael, the Adverse function is basically just an expression level try-catch. It can definitely be syntactically convenient in a language that distinguishes between statements and expressions and only provides a try-catch statement, but it really doesn’t bring anything fundamentally new to the table. (In languages that only have expressions, like ML family languages, try-catch expressions already work like Adverse.) Adverse for void functions is completely superfluous as it just mimics the try-catch statement.
I think that you are mistaken in claiming that Adverse is better than exception handling in that it allows you to separate responsibilities. That is what exception handling already does. Adverse only makes it easier to separate those responsibilities at a finer scale (individual expressions vs statements).
Aside from the syntactical convenience, what is truly advantageous about Adverse, and, in general, about an expression level try-catch, compared to a try-catch statement, is that it essentially allows you to better type check the result of exception handling. Expressed with an ML style syntax for types, a try-catch statement essentially has the type
while a try-catch expression has the type
Obvious from the types is that a try-catch statement has to produce a result via a side-effect, because it doesn’t return any result (it returns unit/void). For example, it has to update a variable declared outside of the try-catch statement. Whether or not both the tried statement and the handler statement update the variable is not apparent at the type level. Consider the following snippet:
The same kind of bug is less likely to be written with an expression level try-catch, because it forces you to return a value from both the tried expression and the handler expression and the types of the return values must agree.
In Factor, there exists the
recoverword which attemps to call a function (word), then calls a recovery function with the same parameters (stack) augmented with the error.Hristo, thanks. So many generics implementations, so little time to learn the best parts of each.
Vesa, it doesn’t bring anything new from a language point of view, but I suspect that code written with disciplined use of Adverse might be better than code written with straight exception constructs – the affordances are different.
Here’s a nice summary of Erlang’s approach to concurrency with a few bits about using its process monitoring features for error handling and recovery. http://ulf.wiger.net/weblog/2008/02/06/what-is-erlang-style-concurrency/
Though what @Vesa says is true, the use of Adverse also could be converted into something that provides easier ways to use generic exception handlers or even insert transactianal semantics into the exception handler.
It should be possibile to organize generic faliure handling functions (that receive both the exception and the parameters) to be re-used throughout the project (Yes, this was possible only using try-catch, but no without re-writting boilerplate code over and over again)
It could even, with a lot of more work (maybe even language modifications) and runtime penalties, try and store the effects of the changes and to not apply them until the success state has been reached. This will probably be very hard (not to say imposible) if there are non-functional calls in the procedure, but is another example of how Adverse could be changed to manage different, interesting, programming styles.
Sorry, I don’t like this solution in its current format, primarily because you’re thinking that every thrown exception would be handled the same. It’s not really generic enough and the concept can’t practicly be extracted out to being able to handle many scenarios.
On my blog I recently talked about why catching System.Exception is a bad idea – http://www.aaron-powell.com/blog/december-2008/should-you-catch-systemexception.aspx.
>Although I like the in-theory concept I don’t think it’s practical, as there are hardly ever 2 places where the same list of exceptions are “expected”, so you’d end up with dozens of these “Adverse” classes, for each combination.
But you do have something similar to conditions. Just extend the exception object:
try { // blah } catch (ExceptionType1 ex) { // blah } catch (ExceptionType2 ex) { // blah } catch (ExceptionType3 ex) { // blah } catch (Exception ex) { // Fail – n – Bail //blah } finally { // Cleanup, if necessary }
Use this where ExceptionTypeN is an object that extends the Exception class. This is supported in every language that supports Exceptions.
That’s an interesting approach, but I’m used to the regular syntax so this one at first seems odd and it will be hard for devs to use it.
That said, I’ve used extension methods to avoid checks for null and encapsulate repetitive code. For example instead of the common way or raising an event we could do something like:
MyEvent.Raise(myEventArgs);
or if it simply uses EventArgs then don’t default it to EventArgs.Empty.
Internally the extension method will check if someone is subscribed.
Something similar with actions, with an extension method that checks that the function isn’t null before calling it.
Action.SafeCall();
Intriguing idea! I’ve posted my thoughts here: http://solutionizing.net/2009/01/10/re-abstracting-away-from-exceptions/