Exceptions / Errors

Some ideas I have formulated over time regarding:

  • Trapping & Handling
  • Throwing & Re-Throwing
  • Run-Time vs. Compile-Time (more java focused)
  • Custom [Exceptions / Errors]
  • [Exception / Errors] vs. Custom Return [Types / Codes]

Trapping & Handling

  • Trap errors when you need to control flow of your program.
  • Trap errors when you need to take specific actions for different errors.
  • Trap errors when you need to notify users of the system
  • In some cases, you will have to trap errors that API developers tell you to trap

What should you do with a trapped error? Few things (not a complete list)

  • Display the error to the user (please do not include stack traces and the like here)
  • Turn off access to certain parts of the program
  • Spawn off certain workflow processes
  • Try recover from it… less likely
  • Fix it… more likely
  • And the most common, log it (and log it once, not 500 times)
DO NOT!!!!

DO NOTHING!!!

Throwing & Re-Throwing

I really do not like the way the inter-web describes Exceptions. Yes they are there to notify people that something went wrong. Yes they can be used to provide meaningful typed information. Yes they can be used to allow people to try and recover from certain kinds of errors. The part that I dislike, is that people seem to only focus on allowing people to recover from errors. This has caused so many API’s to have misused this concept.

Take JDBC or FileIO handling in Java. It is really ridiculous that they throw everything at you besides the kitchen sink. Most of them you cannot programmatically recover from and the worst is that they are compile time Exceptions (Arrrgggghhhh). Take for instance IOException in FileIO. If I am writing a simple program to open a file and something goes wrong in opening, reading, writing, even closing the file… I am not going to be able to recover automagically with only an IOException. Plus I will only really know of that error at run-time. Why then make it compile-time and force me to trap the bugger. What am I supposed to do? Log it, it would get logged if I did not trap it in a simple program anyways. I would definitely have to find out what went wrong and fix it.

I think this is discussion for the next topic, but sufficed to say, I think that you should throw Exceptions as a notifier that something went wrong. They should be typed only if you expect people to be able to deal with that specific error differently and they should be run-time unless… no unless. The programmer should decide which code he wants to secure, not the API developer. Re-throw an Exception if you, yourself, are going to deal with it elsewhere.

Run-Time vs. Compile-Time (more java focused)

Okay, so I pretty much summed up this section in the previous section, sorry. I feel THAT strongly about run-time exceptions and compile-time exceptions. I do not really like having to trap errors that are forced upon me. It leads to this…

// will something work
// oh crap it won't compile
...
try {
	// will something work
} catch (Exception e) {
	// catch all exceptions
	// so that i do not need to catch 5 individual ones
	// do nothing, i just want to test the code
	// oh, wait
	e.printStacktrace();
	// IDE said I should do this
}

or it leads to re-throwing, which in itself can be a pain in the neck.

Why not leave everything run-time exceptions and let me decide what I should trap. Actionscript does it this way, sure it is a scripting language, but it really is nice to secure only the code that I need securing, there is a debug player that handles all unhandled exceptions and the production player just ignores them. Javascript does it this way, but to the other extreme, you have to secure every freaking method, including anonymous functions when doing ajax calls. Only so that you can see what the error is when developing or you can rely on the browser (ahem… one of the gazillion).

Custom Exceptions / Errors

Simply put, they are essentially just identifiers for the type of error, thus you do not need to embed typing information in your Exceptions / Errors or return codes.

why?

The error should be handled differently from other errors (IMHO very seldom the case)

try {
	// code in safe area
} catch (CustomException) {
	// spawn off workflow process
	// notify of malitious activity
	// anything that is outside of the general
} catch (GeneralException) {
	// general error handling
	// logging, rethrowing, disabling, etc
	// sufficient in most cases
}

[Exception / Errors] vs. Custom Return [Types / Codes]

Ever wanted to return multiple results. Well lets encapsulate it in a [class / struct]. Did the method fail, oh well let us return an error code or embed it in our class or struct. I see that this is how most [web / soap] calls are doing it. It is how [C / C++] [did / does] it. I mean it was effective back in the days of C. The only reason I can suggest using custom return objects or codes, is when you are transferring information about a typed error, generic or specific, to another language. If you are within the same language, use the error trapping mechanism in that language. It was designed to do it that way and has its benefits.

The only other reason I can see why you might want to use codes, is when you are dealing with random states and want to convey common error information between them. Like in a workflow which uses different programs, languages, products, tools, etc. Here it makes sense to use codes. Not to the extreme either. Take for instance an error I might trap in a specific step of a workflow process. Within that step, once it has been caught, I know what it is in that step. Rather throw Exceptions within that step instead of codes, which have to be looked up. Then when leaving to the next step use codes, which should be managed in a database somewhere.

Conclusion

This is not a guide or even the right way to do things. It is just my thoughts on exceptions and errors. The the following is a summary of what I have said:

  • Trap when you need to take action or are forced to take action
  • Throw errors when you need to notify that you cannot do what you need to do
  • Only re-throw errors when you are the one dealing with them, later on
  • Make all errors run-time errors (just remember to document what you throw [comments are documentation])
  • Always make sure that there is something in place to notify you of un-trapped errors
  • Create custom Exceptions only when you know that it [would be / needs to be] handled differently from the other 90% of the cases
  • Use return codes between languages or states