DaedTech

Stories about Software

By

Poor Man’s Code Contracts

What’s Wrong with Code Contracts?!?

Let me start out by saying that I really see nothing wrong with code contracts, and what I’m offering is not intended as any kind of replacement for them in the slightest. Rather, I’m offering a solution for a situation where contracts are not available to you. This might occur for any number of reasons:

  1. You don’t know how to use them and don’t have time to learn.
  2. You’re working on a legacy code base and aren’t able to retrofit wholesale or gradually.
  3. You don’t have approval to use them in a project to which you’re contributing.

Let’s just assume that one of these, or some other consideration I hadn’t thought of is true.

The Problem

If you’re coding defensively and diligent about enforcing preconditions, you probably have a lot of code like this:

public void DoSomething(Foo foo, Bar, bar)
{
  if(foo == null)
  {
    throw new ArgumentNullException("foo");
  }
  if(bar == null)
  {
    throw new ArgumentException("bar");
  }

  //Finally, get down to business...
}

With code contracts, you can compact that guard code and make things more readable:

public void DoSomething(Foo foo, Bar, bar)
{
  Contract.Requires(foo != null);
  Contract.Requires(bar != null);

  //Finally, get down to business...
}

I won’t go into much more detail here — I’ve blogged about code contracts in the past.

But, if you don’t have access to code contracts, you can achieve the same thing, with even more concise syntax.

public void DoSomething(Foo foo, Bar, bar)
{
  _Validator.VerifyParamsNonNull(foo, bar);

  //Finally, get down to business...
}

The Mechanism

This is actually pretty simple in concept, but it’s something that I’ve found myself using routinely. Here is an example of what the “Validator” class looks like in one of my code bases:

    public class InvariantValidator : IInvariantValidator
    {
        /// Verify a (reference) method parameter as non-null
        /// The parameter in question
        /// Optional message to go along with the thrown exception
        public virtual void VerifyNonNull(T argument, string message = "Invalid Argument") where T : class
        {
            if (argument == null)
            {
                throw new ArgumentNullException("argument", message);
            }
        }

        /// Verify a parameters list of objects
        /// 
        public virtual void VerifyParamsNonNull(params object[] arguments)
        {
            VerifyNonNull(arguments);

            foreach (object myParameter in arguments)
            {
                VerifyNonNull(myParameter);
            }
        }

        /// Verify that a string is not null or empty
        /// String to check
        /// Optional parameter for exception message
        public virtual void VerifyNotNullOrEmpty(string target, string message = "String cannot be null or empty.")
        {
            if (string.IsNullOrEmpty(target))
            {
                throw new InvalidOperationException(message);
            }
        }
    }

Pretty simple, huh? So simple that you might consider not bothering, except…

Except that for me, personally, anything that saves lines of code, repeat typing, and cyclomatic complexity is good. I’m very meticulous about that. Think of every place in your code base that you have an if(foo == null) throw paradigm, and add one to a cyclomatic complexity calculator. This is order O(n) on the number of methods in your code base. Contrast that to 1 in this code base. Not O(1), but actually 1.

I also find that this makes my methods substantially more readable at a glance, partitioning the method effectively into guard code and what you actually want to do. The vast majority of the time, you don’t care about the guard code, and don’t really have to think about it in this case. It doesn’t occupy your thought briefly as you figure out where the actual guts of the method are. You’re used to seeing a precondition/invariant one-liner at the start of a method, and you immediately skip it unless it’s the source of your issue, in which case you inspect it.

I find that streamlined contexting to be valuable. There’s a clear place for the guard code and a clear place for the business logic, and I’m used to seeing them separated.

Cross-Cutting Concerns

Everything I said above is true of Code Contracts as well as my knock off. Some time back, I did some research on Code Contracts and during the course of that project, we devised a way to have Code Contracts behave differently in debug mode (throwing exceptions) than in release mode (supplying sensible defaults). This was part of an experimental effort to wrap simple C# classes and create versions that the “no throw guarantee”.

But, Code Contracts work with explicit static method calls. With this interface validator, I can use an IoC container define run-time configurable, cross cutting behavior on precondition/invariant violations. That creates a powerful paradigm where, in some cases, I can throw exceptions, in other cases, I can log and throw, or in still other cases, I can do something crazy like pop up message boxes. The particulars don’t matter so much as the ability to plug in a behavior at configuration time and have it cross-cut throughout the application. (Note, this is only possible if you make your Validator an injectable dependency).

Final Thoughts

So, I thought that was worth sharing. It’s simple — perhaps so simple as to be obvious — but I’ve gotten a lot of mileage out of it in scenarios where I couldn’t use contracts, and sometimes I find myself even preferring it. There’s no learning curve, so other people don’t look at it and say things like “where do I download Code Contracts” or “what does this attribute mean?” And, it’s easy to fully customize. Of course, this does nothing about enforcing instance level invariants, and to get the rich experience of code contracts, you’d at the very least need to define some kind of method that accepted a delegate type for evaluation, but this is, again, not intended to replace contracts.

Just another tool for your arsenal, if you want it.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Jason Jarrett
Jason Jarrett
12 years ago

Thanks for sharing on my original ElegantCode post.

After taking a look at what you have here, one problem I have with this approach is how do you tell which parameter failed the null check in the example:

_Validator.VerifyParamsNonNull(foo, bar);

If was foo null or bar null? How do you know?