On swallowing and throwing...

ctodx
19 July 2006

It seems that it's my destiny to talk about exceptions (see here and here on my personal site, as examples). But because this blog entry is going to be about them and it's right here on my work blog, you can rest assured that I'm going to talk about them now in relation to our products.

I read Framework Design Guidelines by Krzysztof Cwalina and Brad Abrams, architects on the BCL team at Microsoft, a few months back just before I was interviewed for my current job at Developer Express. It's a great compendium of topics on designing a framework or a library that's going to be used by many developers. The thing is, as I realized at the time, it's not just about writing frameworks and libraries for sale, much as Developer Express does. The advice in this book also applies to internal developers who are writing reusable code for their colleagues. By following the conventions and standards what Microsoft have done in the .NET Framework (and by understanding the issues they faced and the solutions they took), the people who will use your framework will find it familiar.

Anyway, one of the points in the book that really struck me was made by Krzysztof: "Each exception can carry two main pieces of information: the exception message explaining to the developer what went wrong and how to fix it and the exception type that should be used by handlers to decide what programmatic action to take." (Page 184) Hold that thought.

I would argue that when we use a library or a framework, we expect it to let us know when things go wrong, when it encounters a situation that it can't handle. Suppose some method would fail if we passed in a null reference. We would expect the method to check and to throw a NullReferenceException. If a file wasn't found, we'd expect to see a FileNotFoundException. And so on.

Sometimes we'd accept the framework wrapping a lower-level exception inside its own exception class. So that, for example, an attempt to open a configuration file might result in a file not found, access denied, etc, type exception, but the framework wraps them all inside an "Unable to open configuration file" exception (and to see the real reason why we can look at the InnerException property).

Now this is where it gets interesting and I need some advice from my readers. Although we do have a couple of frameworks (XPO, and XAF in beta), we're mostly known for UI controls.

So, would you expect a UI control like TextEdit to throw exceptions that it couldn't deal with? Or would you expect the control to perhaps swallow (that is catch and not rethrow) as many as it could, and only let out those it couldn't do anything about? Do you find the thought of possibly bad or catastrophic exceptions in your code being discarded by your control? Maybe you think that this question is a "beginner versus advanced" type topic, in that beginners would be confused by unforeseen exceptions so the more the control discarded the merrier, but that advanced developers already have a sophisticated exception handling subsystem and need to "see" them all (or at least those that are not recoverable).

Let's take a concrete example from our code (this is from the hyperlink editor) so that we can get away from hand-wavy generalizations.

  Process process = new Process();
  process.StartInfo.FileName = (e.EditValue == null ? string.Empty : e.EditValue.ToString());
  process.StartInfo.Verb = "open";
  process.StartInfo.WindowStyle = Properties.BrowserWindowStyle;
  try {
      process.Start();
  }
  catch {}

If the process, that is, the browser in this case, doesn't start, for whatever reason, our code just swallows the exception. You, the developer (or the user) don't get to understand why (unless you happen to be running in the IDE and you've activated the "get first-chance exceptions" option); it'll just seem as if the code isn't working. Even worse, the code in the try block may fail due to some entirely different reason, a catastrophic problem like out of memory or a thread abort and again you wouldn't know why. Of course, the entire call stack in the exception is also thrown away, so that you and we would have a much harder problem trying to understand a context-sensitive bug.

My argument here is that, if the catch block were removed, you at least have the choice to do something about an exception that might be raised in this try block. Maybe you don't care about why it fails, just like the code as written, so just add a similar catch block in your code and discard the exception. But if you do care, suddenly you are in a whole better position than before. But either way, you have to do more work.

My questions to you are these:

  • Is this kind of code acceptable in a UI control? Is a UI control just some kind of black-box where we don't care about errors?
  • If it isn't, and we cleaned up this and similar code so that you, as developer, started getting a whole bunch of exceptions, would you know what to do to catch them in your UI layer and properly process them (such as logging them)? Or would it be too disruptive? Would you be ready to have to do a lot more work in your forms?
  • For WinForms controls, that's certainly a problem but it's fairly solvable. What about ASP.NET controls? There your app is running an a server somewhere. There is no UI at the server. If you're not careful, your exceptions get sent to the client as an error page and you know how dumb that can be. But do you know how to catch and process exceptions like that?
  • Given the quote above, I would suppose you'd prefer different exception types for different errors. Or maybe not? Would Exception instances be fine?
  • Are you an advanced developer with a good solution to unhandled exceptions? Do you use something like the Exception Handling Application Block from the Patterns and Practices group at Microsoft?

As you can see, I'm debating whether we should make some pretty major changes to our code, but only if there is support from our customers. Over to you...

Free DevExpress Products - Get Your Copy Today

The following free DevExpress product offers remain available. Should you have any questions about the free offers below, please submit a ticket via the DevExpress Support Center at your convenience. We'll be happy to follow-up.
No Comments

Please login or register to post comments.