Thursday, January 17, 2008

Exception rehandling

Sometimes problem of exception rehandling is occurred in the application.Consider the following situation:
  • You have a class with two methods: LoadData and GetEntity
  • You have ExceptionHandler class that handles exceptions and manages it in something way.
  • Caller classes could call both LoadData and GetEntity
  • You decided to around LoadData and GetEntity methods' bodies with try-catch and handle exceptions using ExceptionHandler.

All is ok. But imaging you call GetEntity from LoadData method and error is occurred in the GetEntity method (e.g. requested entity was deleted). Exception handler handles the exception, process it (e.g. shows message box "Object was already deleted from the storage") and .. what to do further?

  1. Return null signaling that object was not loaded.
  2. Return fake object that signaled the object was not loaded
  3. Rethrow the exception
  4. Throw another exception

Let's consider pros and contras of every approach:

Return null

Pros:

  • You signal that object is not loaded, so no data will be shown;
  • Caller could check for null and make a decision of what to do;

Contras:

  • Caller should always check null instead it gets NullReferenceException (the one of the worst exception I know);
  • Because null is not an often case unnecessary checks will be performed;
  • All the callers have to know about this peculiarity;
  • We should make check and make a decision again of what to do in every place we return null (in Load method and in its caller).


Return fake object

It means returning something like NullValueObject

Pros:

  • NullReferenceException is avoided;
  • If null check is missing in some place we just bind an empty object;
  • Load method could not take into account return value and transmit responsibility on decision making to the caller transparently;

Contras:

  • If no checks made Bind method (that binds data to the form) could bind empty object and it is good if no exception occurred;
  • We should create NullValueObject for the data for every entity. And if the quantity if entities is big and we couldn't support small count of NullValue entities support and creation of such entities could be very hard;

Rethrow the exception

I think it's a bad method at all - to rethrow an exception. E.g. if we rethrow the exception in GetEntity method, then it will be catched in LoadData method and processed in ExceptionHandler again, and there message will be shown again. I think it will confuse user (seems like, "Hey you, you can't understand it from the first time!").

Throw another exception

Pros:

  • Rethrowing another exception (e.g. ExceptionHandledException) allows us to not handle in in the ExceptionHandler again but up on stack as higher as necessary;
  • It allows us not to process incorrect return values;
  • We definitely won't process empty data;
  • Load method shouldn't take care on the possible double error handling and other staff.

Contras:

  • We should catch ExceptionHandledException on the highest level to not obtain UnhandledException
  • If, e.g. absence of data should be processed normally (or in another way than just catching exception) then we should try-catch all the operations that could throw the exception and process it separately in catch.
  • We should know the internals of ExceptionHandler

There are many any pros and contras in every approach. I listed only general.

So as usual, decision depends on the circumstances but the best approaches are: NullValue and ExceptionHandledException. In any case we should clearly define what is error and define the strategy on the application level.

No comments: