Saturday, May 21, 2005

Exception Handling

Many times, I have been asked the way exceptions should be handled. This is a frequently asked question to me, so I am going to post details abuot it here. For Demonstration purpose I have written three small classes. UserInterface deals with user interaction. ProcessService will take care of all processing job or delegation to business layer. BusinessService is our dear business layer. My code goes as following:

using System;

public class UserInterface
{
public static void Main()
{
ProcessService processService =
new ProcessService();

try
{
processService.ChangeStatus(
true);
}
catch(Exception exp)
{
Console.WriteLine(exp.Message);
Console.WriteLine(exp.StackTrace.ToString());
}
}
}


public class ProcessService
{
public bool ChangeStatus(bool status)
{
BusinessService businessService =
new BusinessService();
try
{
return businessService.ChangeStatus(status);
}
catch(Exception exp)
{
//Just say throw. Don't ever say throw exp
throw exp;
}
}
}


public class BusinessService
{
public bool ChangeStatus(bool status)
{
//Some logic to change status

//if logic fails, throw an ApplicationException
throw new ApplicationException ("Some business error ocurred");
}
}


Now can you tell me what is wrong with this code? If you get, very well. If not than just see the code in catch block of ProcessService. I am catching the exception "exp" and throwing it again "throw exp". In this case you will loose original stack trace. A new stack trace will be generated and that stack trace will show you that exception was raised by ProcessService, but originally exception was raised by BusinessService. Your stack trace would be something like this:

Some business error ocurred
at ProcessService.ChangeStatus(Boolean status)
at UserInterface.Main()

This stack trace was not expected! It is not giving me clear picture that what happened. Error was raised by BusinessService but here it is depicted that it ocurred in ProcessService. To correct this thing, don't say "throw exp;". You got to just say "throw". Throw it as you throw any garbage, without touching that. Now your stack trace will look like this:

Some business error ocurred
at BusinessService.ChangeStatus(Boolean status)
at ProcessService.ChangeStatus(Boolean status)
at UserInterface.Main()

Now we have clear picture that Exception was actually raised by BusinessLayer. Here again we have one point to ponder. Do you see that now my stack trace is one line bigger. Can you imagine the scenario when you have 10-20 or more than that calls when exception occurres. It is going to just bloat your system and bring down the performance of your application. My suggestion for this kind of scenarios is "Don't catch exceptions until you want to catch them." Let them bubble upto UserInterface and UserInterface will handle them in a graceful manner. You got to change ProcessService in following manner:

public class ProcessService
{
public bool ChangeStatus(bool status)
{
BusinessService businessService =
new BusinessService();
return businessService.ChangeStatus(status);
}
}


No try{}catch{} in middle layers, OK! Now our stack trace would look like this:

Some business error ocurred
at BusinessService.ChangeStatus(Boolean status)
at UserInterface.Main()

This gives me clear picture that what is happening and where is happening, without much clutter.

one last point before leaving you guys on exception handling is, don't leave your try{} without catch block. Some time you would have coded like try{}finally{}. Never do this again. To read more on this issue go through following article. It will open your eyes.
http://pluralsight.com/blogs/keith/archive/2005/03/31/7149.aspx

Summary
  • Don't ever use throw exception;

  • Catch Exceptions when you really want to catch them.

  • Never leave your try{} block without catch{} block.


2 comments:

Anonymous said...

I haven't gone into the article but Pradeep, I think sometime its wise to throw exception....... What do u think??


Deep kumar

business articles said...

I was searching blogs,and I found your site.Please
accept my congratulations for your excellent work!
If you have a moment, please visit my site:
Business Logic
It pretty much covers Business Logic related stuff.
Have a good day!