Validating method arguments

Last week in “Visual Studio must-know shortcuts” I described my favorite Visual Studio shortcuts that improve my programming productivity. This week I am switching focus to code quality. Defensive Programming practices improve software quality. One of the Defensive Programming techniques is argument validation. The goal is to catch the incorrect data as early as possible. Validating arguments at the beginning of a method and catching the incorrect data early prevents potential bugs from creeping in due to unpredictable data input. It is a simple concept that any decent developer would be eager to embrace. In my experience, this is rarely the case. I would argue that most developers assume correct data inputs and don’t even bother do validate them. Some more experience developers validate the arguments just before consuming them. I do not claim to be any better. I am guilty as charged. I have been trying to force myself to validate arguments of at least public methods, but without much success. I would either forget to do it, or just be in a too much of a rush to validate arguments. It is my unacceptable excuse. If I ever wanted to raise the quality of my code, I would need to change this poor behavior.
Last week I decided to turn a new page and start validating method arguments. This decision raised few questions in my mind. What are recommended guidelines? How to comply with the guidelines? Are there any frameworks or libraries that already do that?

Recommended guidelines
I mentioned that I have been trying to validate arguments for at least all public methods. My approach does not comply with Microsoft guidelines. The guidelines are pretty brief and straightforward. You may reference the link for complete article or continue reading for a summary.

  • It is recommended to validate public, protected, or explicitly implemented members. On validation failure, System.ArgumentException or one of its derived types should be thrown.
  • In case argument does not support null, it is recommended to throw System.ArgumentNullException.
  • Enumeration arguments should be validated. Using System.Enum.IsDefined for enumeration range check should be avoided. The reason is that any integer can be cast to a valid enumeration value regardless whether the value is defined in the enumeration. In translation, this is not recommended:
// Not recommended
public static bool IsWorkDay3(WeekDay day)
{
    if (!Enum.IsDefined(typeof(WeekDay), day))
    {
        throw new InvalidEnumArgumentException("day", (int)day, typeof(WeekDay));
    }
    return day >= WeekDay.Monday && day <= WeekDay.Friday;
}

The recommended approaches are:

public static bool IsWorkDay1(WeekDay day)
{
    if (day < WeekDay.Sunday || day > WeekDay.Saturday)
    {
        throw new InvalidEnumArgumentException("day", (int)day, typeof(WeekDay));
    }
    return day >= WeekDay.Monday && day <= WeekDay.Friday;
}
public static bool IsWorkDay2(WeekDay day)
{
    switch (day)
    {
        case WeekDay.Sunday:
        case WeekDay.Saturday:
            return false; case WeekDay.Monday:
        case WeekDay.Tuesday:
        case WeekDay.Wednesday:
        case WeekDay.Thursday:
        case WeekDay.Friday:
            return true;
    }
}
  • Mutable objects may have changed after they were validated. Therefore, a private copy should be made. The object copy should be used for validation and processing. Once I had become familiar with the recommended guidelines, I started thinking how to painlessly comply with them on every day basis.

How to comply with the guidelines? 
My first thought was to write one ‘if’ statement for each argument restriction. That meant that I would have at least as many ‘if’ statements as arguments at the beginning of a method. For instance:

// Initial, not so good approach
private static void Print(string msg, int count, Emplyee emp)
{
    if (string.IsNullOrEmpty(msg))
    {
        throw new ArgumentException("Message should not be empty", "msg");
    }
    if (count < 1)
    {
        throw new ArgumentOutOfRangeException("count",
        String.Format("count should be greater " +
        "than 0. The actual value is {0}.", count));
    }
    if (null == emp)
    {
        throw new ArgumentNullException("emp",
        "Employee should not be empty");
    }

    // Method's work....

    if (string.IsNullOrEmpty(result))
    {
        throw new ArgumentException("Result should not be empty", "result");
    }
    return result;
}

This approach seems painful. It consists of mostly repetitive code boring to write. It also reduces the method readability. My second thought was to write a library and put all this repetitive code in it. Before plunging into code writing, I decided to do some research. I wanted to see how other people had handled similar problems. To no surprise, there was a lot of material written on this topic. I found out that there have been several well-written libraries for argument validation.  

Argument validation library
I looked at few different libraries. They were all very robust, extensible, and complete. They were capable of validating all data types for many diverse conditions. After a long deliberation, I decided to start using CuttingEdge.Conditions, created by Steven van Deursen. I chose CuttingEdge.Conditions because its functionality completely satisfies my current needs. Another factor was the fact that it has been actively maintained. Reading Steven’s blog and discussions in the comments I realized that he has been truly concerned for the library users. He discusses ideas and potential improvements with CuttingEdge.Conditions user base. Even though my needs were only precondition validation, CuttingEdge.Conditions also supports postcondition validation. It is capable of validating values being returned from a method. Some may argue that this may negatively affect application performance. In my opinion, it is a good idea to perform postcondition validation in debug builds, at least. I have been praising CuttingEdge.Conditions, but I can’t describe its full potential as well as its original author, Steven, can. I suggest you visit his blog for more in depth information. Having said that, I will only show how the above example would look like written using CuttingEdge.Conditions library.

private static void Print(string msg, int count, Emplyee emp)
{
    Condition.Requires(msg, "msg").IsNotNullOrEmpty();
    Condition.Requires(count, "count").IsGreaterThan(0);
    Condition.Requires(emp, "emp").IsNotNull();

    // Method's work....

    Condition.Ensures(result, "result").IsNotNullOrEmpty();
    return result;
}

My initial impressions of the library have been nothing but positive. I really like its easy of use and clean code. I will try to post an update to the post once I get more use out of it in everyday development.  

Conclusion
Writing this post was a good learning experience. It has exceeded all my expectations. I am confident that practicing the Defensive Programming technique, Argument Validation, utilizing CuttingEdge.Conditions library will improve my code quality. I wish anyone reading this gets inspired and start embracing Defensive Programming practices.

Next week
Slow Windows start-up? In the next week’s post, “Speeding up by delaying”, I will show how to stop wasting time waiting for Windows to start-up.

Leave a Reply

Your email address will not be published. Required fields are marked *