Geeks With Blogs

News



Microsoft Store

Support This Site


AddThis Social Bookmark Button

Locations of visitors to this page

Subscribers to this feed

TwitterCounter for @sdorman

Creative Commons License


Scott Dorman Microsoft MVP, Software Architect, Developer, Author

My post on the Null Object pattern has generated some interesting dialog. One of the trends that I have seen is the idea that defensive programming means your code should fail as early as possible. I couldn’t agree less.

According to Wikipedia,

Defensive programming is a form of defensive design intended to ensure the continuing function of a piece of software in spite of unforeseeable usage of said software. The idea can be viewed as reducing or eliminating the prospect of Murphy's Law having effect. Defensive programming techniques are used especially when a piece of software could be misused mischievously or inadvertently to catastrophic effect.

While this is a good definition, I think it still leaves much to be desired. The Wikipedia entry goes on to say that defensive programming is one approach to improving software quality by “Making the software behave in a predictable manner despite unexpected input or user actions.”

I think this is the closest definition that actually conveys what defensive programming is all about. The idea behind defensive programming is that the application should behave in a consistent and predictable manner even in the case of unexpected conditions.

There are a lot of different ways to achieve this and they are all different depending on what you are trying to accomplish with the code, the programming language, and the control structures being used. For example, considering a switch statement:

switch (Orientation)
{
   case Orientation.Horizontal:
      break;

   case Orientation.Vertical:
      break;
}

This is perfectly acceptable code, right? Remembering that enumerations are simply numeric (generally integer) values, it is entirely possible for this switch to get passed a numeric value that doesn’t correspond to either Horizontal or Vertical. In that case, there is the possibility of the switch, or code following the switch, to crash. One option to handle this would be to add a default case to the switch:

switch (Orientation)
{
    case Orientation.Horizontal:
        break;

    case Orientation.Vertical:
        break;

    default:
        break;
}

In the default case you could throw an exception (if that’s the appropriate behavior) or, more likely, you take some action that ensures either the remaining code doesn’t execute or at least doesn’t crash.

Looking at another example, this time casting, shows some other ways to program defensively. A common scenario for casting is in UI programming and handling events.

private void button1_Click(object sender, EventArgs e)
{
    ((Button)sender).Text = "You pressed a button";
}

Again, this code looks perfectly reasonable and will work just fine until someone accidentally assigns this event handler to something other than a button. Once that happens, the code will crash since sender won’t be castable to a Button. There are several different ways to handle this but the simplest (at least in my opinion) is

private void button1_Click(object sender, EventArgs e)
{
    Button button = sender as Button;
    if (button != null)
    {
        button.Text = "You pressed a button";
    }
}

Yes, it is a bit more code but it also guarantees that no matter what happens if the object that raised the event is not a Button, the code won’t crash. You could have chosen to throw an exception (or just let the exception generated by the runtime bubble up the call stack until it’s handled, but that may not be desirable depending on what you are doing.

The bottom line is that catching exceptions (not throwing them, but catching them…and all exceptions will eventually be caught, but possibly not in a way you intended) is expensive and if there are techniques that allow your program to continue functioning properly or otherwise gracefully handle exceptional conditions, known as “defensive programming”, you should opt for that approach.

Technorati Tags: ,
Posted on Friday, July 4, 2008 9:26 AM .NET (General) , .NET (C#) | Back to top

Copyright © Scott Dorman | Powered by: GeeksWithBlogs.net