Enums versus Exceptions: An new, Agile approach to application error handling
As Agile teams recognize the overhead of using throwable objects, the enums versus exceptions debate is beginning to rage, but smart developers know that using enums means better error handling.
Effective error handling is a challenge that application development teams must face head on. However, with the introduction of enums in Java 5, Agile development teams are realizing that there are less resource intensive ways to handle errors, all of which has caused the enums versus exceptions debate to rage on.
When it comes to design patterns and best practices, some ideas, such as separating readers from writers, are good. Other ideas, such as limiting developer access to pointers, are bad. Finally, some ideas, like favoring exceptions over enumerators, are just plain old ugly.
Are exceptions evil?
Not only are exceptions ugly, but the associated stack and memory cost can often make using exceptions unnecessarily expensive. But is there a better way to handle unexpected problems in code than using exceptions? There are indeed, and to demonstrate a much better alternative, let's baseline the discussion by looking at exactly how Exceptions are used and created. The following is a simple Exception class:
public class Exceptional extends Exception { /* Often this is empty, as the only need is to create a new Exception type */ }
The net effect of using an exception to simply create an response, as innocent as we might imagine it to be, is to create a code and memory sandbar. Here is the typical switch like code that gets created to handle an Exception:
try { ... } catch(Exceptional ex) { } catch(IOException ex) { } catch(Exception ex) { }
If developers are simply looking to create an intra-process communication flag, then why bother creating a object of type Throwable in the first place? Why not simply use an enumeration instead?
While an enumeration is indeed a class, such is a class is free from the onerous lifecycle associated with exceptions:
public enum foonum {
one, two, three;
public static void SayHello(foonum val) { System.out.println("Hello " + val); }
public void greeting() { System.out.println("Greetings " + this); }
public static void main(String ... args) { SayHello(foonum.two); foonum.two.greeting(); } }
Rather than using the keyword new to create instances, each member in the enum itself is garbage reliant and ready for us to use at will.
Benefits of enumerations
Ever concerned with higher performance and efficiencies, C++ developers have traditionally been able to turn off things like runtime type identification and exceptions. The ability to turn-off bloat-features in this manner is one of the reasons why C++ will always be far more efficient than .NET or Java.
But since enumerators arrived latter in Java than they did in C++, many developers continue on with what has become a traditional use of exceptions. But using an enum, as in the following example, is much more favorable:
public class Alternative { enum Exceptional { ea_Good, ea_Bad, ea_Ugly } public Exceptional Groovy() { return Exceptional.ea_Good; } }
So rather than tossing a 50-pound thrown wrecking ball around our code, why not simply return an open-ended enumeration instead?
public void Cool() { switch(Groovy()) { case ea_Good: break; case ea_Bad: break; case ea_Ugly: break; default: break; } }
Indeed, rather than working so hard to merely let a future exception slip through, when using a switch, the default block works harder than any type of finally statement can since no super-block flags need to be set:
boolean imadoofus = false;
try { ... } catch(Exceptional ex) { imadoofus = true; } catch(IOException ex) { imadoofus = true; } catch(Exception ex) { imadoofus = true; } finally { if(imadoofus) { ... } }
The liberal use of even a single enumerator set can make code more readable, maintainable, and easier to enhance. Every developer needs to keep up with the ripple effects that occur when a standard is updated. Reserving the creation of custom Exceptions for managing far less-recoverable Errors, and instead using enums, is one new practice developers need to get used to.
What new Java 7 features have impacted the way you code the most? Let us know.