.NET Zone is brought to you in partnership with:

.NET developer/architect. Been coding since 1996. Jonas is a DZone MVB and is not an employee of DZone and has posted 20 posts at DZone. You can read more from them at their website. View Full User Profile

What Are Exceptions?

04.11.2013
| 3246 views |
  • submit to reddit

This blog has been quiet for a while. I am currently writing a book about localization. Me and my partner is also getting close to release of our new startup. One of it’s features is to automatically catch unhandled exceptions and send them to a webservice for analytics. But to take full advantage of that you’ll have to use a set of exception handling best practices. I’m therefore going to write a set of exception articles. The series will end with the release of our service.

What is so exceptional with exceptions?

Meet Bob:

bob

He got more money than he can handle. Hence every time he shops he just swipe that bling bling card and pays.

Meet Sam

poor-man-begger

He is not as fortunate and every dollar counts. That means that he doesn’t just swipe his credit card and expect it to work. He usually stops by at the ATM before to check the balance.

What I’m saying is that both of them got the use case “Pay items with a credit card”. But as Bob doesn’t expect the card to be empty he just swipes that bling bling card without doing any prior checks. Sam, on the other hand, expects the payment to fail. He’ll therefore make sure that there is enough money on the card before swiping it.

Now imagine that someone has hacked Bobs card so it’s empty. He’ll go into the shop with that big fat grin and shop like a madman as he usually do. But this time he gets a surprise: There is no money on the account. He understands what’s wrong, but not why. Hence there is really nothing that he can do about it. He’ll have to go home and try to understand what happened and also try to prevent it from happening in the future.

And that’s what an exception is.

Code example

If you have an XML file which is shipped with your product, for instance an product list, you expect it to exist. If it doesn’t, there is not much you can do about it. Hence something exceptional has happened.

If you on the other hand have a XML file which contains a cache of the most recently used products you’ll expect that file to not exist the first time. If it doesn’t you simply create it and add the product that the user is currently working on.

What I’m saying is that what’s exceptional depends on the use case. In one case it’s vital that the file exists, in another case you can continue by just creating the file.

Exceptional cases are when you can’t rescue the situation to allow the application to continue as expected.

If we translate both cases into code the first one will look something like this:

public IEnumerable<Product> GetProducts()
{
    using (var stream = File.Read(Path.Combine(Environment.CurrentDirectory, "products.xml")))
	{
		var serializer = new XmlSerializer();
		return (IEnumerable<Product>)serializer.Deserialize(stream);
	}
}

In the above example you do expect the file to exist. So you should not try to handle any exceptions in it (as there is really no way to recreate the product list).

The other example on the other hand expects the file to not exist. So we do check if the file exists:

public IEnumerable<Product> GetCachedProducts()
{
	var fullPath = Path.Combine(Environment.CurrentDirectory, "ProductCache.xml");
	if (!File.Exists(fullPath))
		return new Product[0];
		
	using (var stream = File.Read(fullPath))
	{
		var serializer = new XmlSerializer();
		return (IEnumerable<Product>)serializer.Deserialize(stream);
	}
}

When to catch exceptions

So when should you catch exceptions?

When you can make the method return what is expected of it.

Let’s use the above examples again:

IEnumerable<Product> GetProducts()

This method says that it should always return a list of products. If you can do that by catching an exception in it, go ahead and do it. If you can’t, you should not catch exceptions in it.

IEnumerable<Product> GetCachedProducts()

This method is a bit trickier. We could catch FileNotFoundException in it and use that to detect if the cache file is missing. That, however, communicates that we expected that the file should exist, but that we can rescue the situation by handling the exception. That is not true. We do expect the file to not exist.

Summary

Exceptional cases are usually something that you can’t foresee. It can be a logical error made by you (read: bug) or something out of your control (like OS/Network/Disk errors). That means that you can’t in most cases handle those errors even if you try by catching them. Or even worse: You catch them, fail to handle them, and have by doing so hidden a bug which will be much harder to find and solve. Simply don’t do anything with exceptions that you can’t handle.

If you want to catch exceptions to log them, do that in your top layer (like WCF or ASP.NET MVC). Your code will get a lot less cluttered.

Published at DZone with permission of Jonas Gauffin, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)