Exceptional Traveler

James Fenn |

Some time ago, I read an article by Chet Haase on the topic of a new style of programming called "Exceptional Programming". In this style, programs are written in a way that handles all possible errors that could be thrown; your programming is Exceptional, after all. It shouldn't fail because of an uncaught ClassCastException and such. And when you cannot beat the enemy, you must become it.

In other words, Exceptional Programming is a style in which you use thrown exceptions as the only control structure.

However, to me the article written by Chet Haase seemed a little incomplete. Sure, it explained the basics, but there were few examples of how such a concept would actually work. While I was discussing this with a friend, they suggested that I write an implementation of the Traveling Salesperson problem to demonstrate its use. And so I took it upon myself to bring this marvelous beauty into the world.

Pre-determined Rules

The article is a little vague about the requirements for a program to be "Exceptional", but a code snippet from the article establishes a few guidelines, from which I have made up some more specific rules for this program.

try {
    someMethod();
} catch (NormalException e) {
    try {
        anotherMethod();
    } catch (NormalException e) {
        try {
            yetAnotherMethod();
        } catch (NormalException e) {
            throw new NormalException("Everything's fine");
        }
    }
} finally {
    throw new NormalException("Everything's fine");
}

The basic rules stated in the article were as follows:

Inferences

As it has been over a year since the article was written and there have been no updates (this is to be expected, given that the article was written almost entirely as a joke), this snippet was likely only provided to illustrate how ridiculous the idea of actually writing a program using this stupid and inefficient style would be. That said, there are some useful bits of knowledge that can be extracted from it.

Modifications

Now, as I was writing the program, these rules turned out to be unexpectedly strict, and were especially annoying when working with the standard Java APIs such as List or Scanner. As such, I made a few modifications/exceptions (ha) to these rules.

Explanations

Chronological Order

As programs by definition are meant to run in chronological order, I had a bit of an internal debate as to whether multiple consecutive statements should be allowed - and if not, does the restriction include the finally block? Eventually, I decided on "no", but decided to allow the finally block on one condition:

This allows one specific functionality which is necessary in order to make use of the standard Java APIs: throwing an exception even if one is not thrown by a statement (or throwing a different one if it is).

Statements Without Exceptions

If a statement does not always throw an exception, it is fairly easy to modify a try/catch block so that it does:

try {
    willNotThrowAnException();
} catch (Exception e) {
    throw e; // this does not do anything
} finally {
    throw new ArbitraryException();
}

There. Now the method willNotThrowAnException() will always throw an ArbitraryException when it is run, right? However... what if you want a different result in the event that an exception is thrown by the method? If willNotThrowAnException() throws an exception in this snippet, then even though it gets passed to the catch block (which throws it again), the finally block is still run before the original exception is thrown, effectively overwriting it with the ArbitraryException either way. In order to combat this, I racked my brain and actually took advantage of this overwriting behavior to come up with this uselessly complex snippet:

try {
    try {
        throw new ExceptionNotThrownException();
    } catch (Exception e) {
        throw e;
    } finally {
        try {
            mightThrowAnException();
        } catch (Exception e) {
            throw new ExceptionThrownException();
        }
    }
} catch (ExceptionThrownException e) {
    // an exception has been thrown
} catch (ExceptionNotThrownException e) {
    // an exception has not been thrown
}

Yep, this is definitely complicated and stupid. Just what I needed! Now, if mightThrowAnException() throws an exception, it will overwrite the ExceptionNotThrownException being thrown in the original try block and replace it with its own ExceptionThrownException, altering the flow of the program.

Assertions

As the primary joy that comes from Exceptional Programming is coming up with a way to throw an exception in a specific situation, I also added my own rule regarding the use of assertions:

Another possible argument for this is that assertions are intended mainly for use as tests and should not show up in the code of an actual application. But mainly, in the view of Exceptional Programming, they are kind of cheating. Half of the fun of Exceptional Programming is figuring out how to throw an exception in certain situations so that your program will do what you want - an example of which is below. If assertions could be used here, the structure would be the same, but not nearly as fun to write.

try {
	try {
		throw new ArbitraryException();
	} catch (ArbitraryException exce) {
		throw exce;
	} finally {
		try { // assert which distance is smaller
			int shouldNotBeZero = 1 / (int) Math.floor(nearestDistance / nearestDistance2);
		} catch (ArithmeticException exce) {
			throw exce;
		}
	}
} catch (ArbitraryException exce) {
	// "nearestDistance2" is smaller
} catch (ArithmeticException exce) {
	// "nearestDistance" is smaller
}

Fin

And that's it! Simple, right? Yeah...

If you're still curious, you can find the source code for the resulting atrocity here. It is partly documented, at least, though I don't recommend trying to figure out how any of it works. It does, though, and that is enough.