My programming is always Exceptional.
This program is a joke. It is not serious. Please do not take this program seriously. It is not a good demonstration of my programming skills. Do not use this program as reference material. Please don't use this program to educate yourself or others on Java programming. Avoid looking at this program for extended amounts of time. If you experience dizziness or a loss of balance while viewing this program, stop staring at it in awe and seek medical help immediately. If you feel the effects of depression or anxiety after becoming aware of this program's existence, please see a qualified counselor for assistance.
The idea for this program was taken from Chet Haase's article for Pointer IO on Exceptional Programming, which describes a programming style using just try/catch blocks and exceptions as the only control structure.
This specific program takes a set of coordinates as input and uses a basic double neighbor heuristic to find the (probably) shortest (ish) possible path that crosses all of the points. It also keeps track of the total distance that has been covered, and outputs it with all of the points at the end of the program.
Obviously, this is a Java program. In order to run this program, download the source code and run the following commands:
javac Main.java
java Main
The program will then prompt you to input coordinates, after which it will pass the coordinates to TravelingSalesPerson.java
, which will calculate and output the resulting order.
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:
if
, else
, while
, for
, and even return
).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.
finally
blocks are allowed.catch
or finally
block are:
throw
statement.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.
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:
finally
block is used, an exception must be thrown in the try/catch/finally block that it is a part of.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).
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.
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.
Please do not contribute to this project, it is horrific enough already. However, if you would like to contribute, you can see CONTRIBUTING.md for more information.