Keywords: Exception Handling in Java, out parameters in C#
I’ve been thinking a lot about error handling lately. And my new mantra is locality, locality, locality.
My day to day programming work is primarily in C#, but it used to be in Java. I still do some work in Java. Last year, I designed and built (with help) a multi-tier web application for internal application form processing. It included an (MVC) presentation layer, a business layer, and a data access layer. Each form contains up to ~400 different kinds of data fields that may or may not be present in each form instance (depending on how it is filled out.)
To cut to the chase, I was fresh off of a large Java project and, faced with the design of an error handling system for the web application, I chose to base the error handling system around throwing and catching exceptions. In Java, this choice tends to lead to a good design because the language helps you keep the error handling local. If a method in Java throws an exception, the compiler will enforce that any clients must either catch the exception or declare it to be thrown. Thus, the programmer must always be conscious of the decision: do I handle the error locally (near the source of the error) or do I pass it along?
In C#, the compiler enforces no such rule. You can theoretically achieve similar results with discipline; but in practice, after a few months of a couple of programmers set loose on the codebase with random enhancement requests, exceptions get thrown about willy nilly, and can wind up causing mayhem in stack frames and/or in code far away from the cause of the actual error. So discipline breaks down, generally along the lines of “I didn’t know method XYZ() was going to open a file/connect to a database/use a web service/etc.” (And yes, I am often one of those programmers ;-)
We’re currently refactoring the business and data access layers to make things more efficient, and one of the changes I’m including is to deemphasize the use of exceptions and use more old-fashioned return values and out parameters. Using an out parameter in C# for error messages and statuses leads to greater compiler enforced locality in error handling. At least it is halfway there: while the programmer must set the value of an out parameter before control leaves the method, the client doesn’t have to examine the returned value. But discipline is more easily enforced because I can make a stronger case that a return value should be checked since it is local, eg- it’s being set in the very next stack frame. And I can more easily check by reading the code.