Strategies for Successful Development

Process and technology for small teams building real software

Archive for the ‘Tips, Tools, and Tricks’ Category

Swallows, logs, throws, and ignores (exceptions)

Posted by S4SD (Seth Morris) on 2011/05/10

This post is in response to Logging is the New Exception Swallowing by Martin Jarvis.

I am always glad to see someone pointing out that exception handling is horribly handled!

First, a disclaimer. I’m a bit old school. I think exceptions are generally bad things that have led to worse code and worse error handling. I recognize that I am in the minority and that the ship has sailed, though.

Mr. Jarvis is raising a point which goes to the heart of the problem. We write code that swallows (or logs unimportant exceptions because we get yelled at for swallowing exceptions) because our libraries use exceptions poorly and because our development culture uses exceptions even more poorly. Exceptions, no matter what academic purists and book authors claim, are used in to mean any of several conditions in the real world, and they’re used with the same syntax despite the semantics.

In the wild (including in the .NET library), an exception could mean any combination of:

  • The function couldn’t perform its contract (the classic definition of an exception).
  • The function is informing you of a side effect (“Hi. I’ve consumed all your disk space. Have a nice day.”). This may not even be an error.
  • Some internal object threw an exception. I hope the library correctly listed every exception that type it can throw AND the functions it calls can throw. And that they correctly listed this.
  • There is an informational message you should log, but you can continue.
  • We’re done with a loop. The exception indicates the end of some condition (reading a file, network access, etc.)

And we may want to respond wildly differently:

  • The system state is inconsistent, exit the app ASAP. This is often the correct answer in client apps.
  • Try a different function.
  • Move on. For example, some type conversion failed and the original value is as good as it gets.

We get in this situation because we use exceptions poorly, but the response can’t be “Use exceptions better.” We have to deal with libraries that we can’t change, we have to deal with legacy code that we shouldn’t change, our team members have–and will continue to hire–people of varying skill, and writing exception handling isn’t the reason we’re writing software. We’re writing software to meet some business need (or some general need, if you aren’t comfortable with the word “business”). Exceptions take up too much of our time (as does anything that isn’t about making our users and customers happier and more successful).

For a fabulous example of the current situation, consider the joys of int.Parse() and the need for int.TryParse(), which has a horrible legacy syntax and obfuscates the logic of the code.

So we’re left with a mix of reasonable responses to exceptions:

  • Catch the exceptions we can do something useful with, even if that is crashing, and let some unknown error handler above us catch the others. This is the most common suggested solution.
  • Catch the exceptions we have some alternate response to and swallow others with some default action.
  • Swallow everything because failing what we’re doing is not critical. Some comment to this effect makes code reviewers happy (and is generally good for other reasons!), but the same boilerplate comment in many places actually decreases readability. Differentiate Decision from Idiom.
  • Log the exception so we don’t get dinged in a code review for ignoring exceptions. Off-site code reviews by outside consultants love to make long lists of correctly swallowed exceptions and present them managers who are less-technical or who don’t have a familiarity with the code or platform and can’t identify which are well-considered and which are just lazy1.

This post calls out a good response that is often left implicit, because it also gets dinged in code reviews and it is a little scary:

  • Let any unknown upstream called catch exceptions, if they can, and hope they can handle it

Here’s what I’d like to add: It’s a good response when a few conditions are met. In other conditions, other responses make sense (of course). Code should express its intent and assumptions to other programmers who will have to maintain it for years to come; it needs to be readable as to which conditions the programmer assumes are present.

  • All exceptions are handled here. When the libraries change, this code needs to be re-evaluated for exception handling.
  • Known exceptions are handled, but bailing out to upstream handlers is acceptable. Finally blocks are used correctly, for example.
  • Exceptions are informational, but shouldn’t stop execution.
  • Downstream code throws exceptions when this code doesn’t care and downstream functions use the “pass exceptions along and hope they’re handled” philosophy. We just want them to go away.

Also, note that there is a significant different between handling exceptions around one statement, such as int.Parse(), and a statement block which may throw exceptions from any of several calls.

I augment coding standards with something less draconian: a “stop” list (https://s4sd.wordpress.com/2008/09/17/development-red-lights/). This is a list of statement, idioms, and techniques which require stopping, stepping back, and explaining to another (senior) developer. If a second set of eyes agrees that it’s reasonable in this context, you go forward (and say who agreed in the checkin comment!). Swallowing exceptions is a good Stop item.

Make a considered and deliberate choice in how to handle exceptions. Then make it clear. Code that swallows (or logs) any exception indiscriminately won’t go away. It’s impossible to handle exceptions better than your downstream calls throw them and real, reasonable conditions arise where exceptions in downstream code just don’t matter. As an obvious example, an exception from an error logging call (say, network or disk unavailability is preventing logging) shouldn’t be logged.

Just for fun, here’s a cute way to document swallowing errors. “Cute trick” is usually a code phrase for “bad for maintenance,” but maybe this one is reasonable.

   1: using System;

   2:  

   3: namespace ExceptionSwallowing

   4: {

   5:     class Program

   6:     {

   7:         delegate void statementblock();

   8:         static void SWALLOW_EXCEPTIONS(statementblock fn) {try{fn();}catch(Exception){;}}

   9:  

  10:         static void Main(string[] args)

  11:         {

  12:             SWALLOW_EXCEPTIONS(()=>

  13:             {

  14:                 Console.WriteLine("Example of executing a Statement Block");

  15:             });

  16:             Console.WriteLine();

  17:  

  18:             try

  19:             {

  20:                 Console.WriteLine("Throwing an exception that should be swallowed");

  21:                 SWALLOW_EXCEPTIONS(() =>

  22:                 {

  23:                     Console.WriteLine("Throwing an exception that should be swallowed");

  24:                     throw (new Exception("ExceptionToBeIgnored"));

  25:                 });

  26:                 Console.WriteLine("  Success: the exception was correctly ignored");

  27:             }

  28:             catch (Exception e)

  29:             {

  30:                 Console.WriteLine(  "Error: the exception was caught but should have been swallowed: " + e.Message);

  31:             }

  32:         

  33:             Console.WriteLine();

  34:             Console.WriteLine("Press any key to exit");

  35:             Console.ReadKey();

  36:         }

  37:     }

  38: }



Listening to: Lou Reed – New York – Romeo Had Juliette

1) In software, about half the time “Lazy Programmer” is used as a code phrase for “pressured to meet deadlines,” “not given sufficient training,” or “no longer working here and easy to blame.”

Advertisements

Posted in Dev Leads, Tips, Tools, and Tricks | Tagged: , , , | Leave a Comment »

Custom searches in your toolbar. Or, Desktop tools mashup, too.

Posted by S4SD (Seth Morris) on 2008/09/10

When I saw Windows Live Search Macros only a few hours after finishing a writeup for a client on the new search provider features in IE8b2, I was pretty excited.

If you don’t know Live Search Macros (I certainly didn’t), they are pretty simple. You go to http://search.live.com/macros/ and build a search string to modify search results. You can use all the operators available on Windows Live, such as filetype, hasfeed, contains, language, site, and the all-important prefer. If you save the results, you can go back to a page created for you to run a Windows Live search with those modifiers already added.

For example, http://search.live.com/macros/andyed/scifi/?FORM=MACWLG presents a Windows Live search screen that restricts results to several popular science fiction sites. And on each of these pages you get the little orange arrow that indicates you can add a new search provider.

This is all very nice, but you don’t need that to make a Windows Live Search Macro to get a custom search provider that does this, and you can use any search engine (including site-specific engines like Amazon or IMDB) and any syntax that engine supports.

Let’s say I often search for information on a .NET programming concept or term. I know searching on “select” alone won’t give me very useful results, even if I use a categorizing search engine. I need to give the engine some more context, so I add terms that aren’t specific to my query, but instead are general to my query domain. This is exactly what we shouldn’t have to do.

I probably use a search like .NET C# (WinForms or LINQ) +select 

This is the same problem Windows Live Search Macros were created to solve, but I don’t want to go to a web page every time I do it (and maintain a list of these pages) and I also don’t want to be restricted to Windows Live Search.

So let’s solve the problem on the desktop using IE7 (or IE8). Click arrow by the search box and select Find More Providers…. You will be taken to this page, with a list of companies that have convinced Microsoft to surface them and a box to create your own provider. What isn’t obvious is that the search string you use to create a provider doesn’t have to be minimal: any legal search string for your search engine of choice will work, as long as the MS website can find the word TEST in it.

So I go to a search engine, let’s say www.clusty.com, and enter the domain-specifying query I use often enough to want to automate. automate. I get this url: http://clusty.com/search?input-form=clusty-simple&v%3Asources=webplus&query=%22.NET%22+%22C%23%22+%28WinForms+OR+LINQ%29+%2BTEST.

By putting that into box 3 of the form naming it “General C# Search” I have a search provider on my drop-down that does what I want.

It isn’t any better than the Windows Live Search Macros, other than letting me choose my search engine and it let me get into the details a little bit and feel like all the moving parts were under my control. And sometimes, that’s enough.

 


Listening to: Laurie Anderson – Strange Angels – The Day The Devil

 

Posted in Tips, Tools, and Tricks | Leave a Comment »