Precondition and Invariant Checking
The Problem
If you find yourself immersed in a code base that is sometimes or often fast and loose with APIs and internal contracts between components, you might get into the habit of writing a lot of defensive code. This applies to pretty much any programming language, but I’ll give examples here in C#, since that’s what I code in most these days. For example, this is probably familiar:
public class MyClass
{
public Baz ClassBaz { get; set; }
public void DoSomething(Foo foo, Bar bar)
{
if(foo == null)
{
throw new ArgumentNullException("foo");
}
if(bar == null)
{
throw new ArgumentNullException("bar");
}
if(ClassBaz == null)
{
throw new InvalidOperationException("Object invariant violation - baz cannot be null");
}
//Whew - finally, get down to business using foo, bar, and baz
}
}
That’s an awful lot of boilerplate for what might be a very simple method. Repeating this all over the place may be necessary at times, but that doesn’t make it pretty or desirable. In an earlier post, I wrote about Microsoft’s Code Contracts as an excellent way to make this pattern a lot more expressive and manageable in terms of lines of code. However, for those times that you don’t have Code Contracts or the equivalent in a different language, I have created the pattern I’m posting about here.
Poor Man’s Code Contracts
As I got tired of writing the code above on a project that I’m currently working on where we do not bring in the Code Contracts DLL, I started thinking about ways to make this sort of checking less verbose. The first thing I did was to start changing my classes on an individual basis to look like this:
public class MyClass
{
public Baz ClassBaz { get; set; }
public void DoSomething(Foo foo, Bar bar)
{
VerifyArgumentOrThrow(foo);
VerifyArgumentOrThrow(bar);
VerifyOrThrow();
//Get down to business using foo, bar, and baz
}
// This guy validates class invariants
private void VerifyOrThrow()
{
VerifyArgumentOrThrow(ClassBaz);
}
private void VerifyArgumentOrThrow < T > (T arg) where T : class
{
if(arg == null)
{
throw new ArgumentNullException("MyClass precondition/invariant");
}
}
}
If you’re not familiar with the concept of generics, you can check out this link: generics. Basically, the idea is similar to templating in C++. You define a class or a method that takes a type to-be-defined-later, and it performs some operations on that type. Whenever you have List < Foo > , you’re using the List class, whose signature is actually List < T > . The “where” clause on the method just puts some constraints on what types the compiler will allow–here I’m restricting it to reference (i.e. class) types, since value types are never null and this wouldn’t be appropriate. If you try to pass an int to that method, the compiler will complain.
Anyway, that implementation doesn’t save a lot of code here, but imagine if MyClass had 10 methods. And imagine if there were 400 MyClass-like classes. Then, the savings in terms of LOC really adds up. I was pretty happy with this for a few classes, and then my code smell sense was telling me that I shouldn’t be writing that generic method over and over again.
In the interest of DRY (Don’t Repeat Yourself)
So, what to do? For problem solving, I usually try to think of the simplest thing that will work and then find its faults and ways to improve on it. In this case, the simplest thing that would work would be to make VerifyArgumentOrThrow
Generally, I try to avoid static methods as much as possible because of their negative effect on testability and the fact that they’re procedural in nature. Sometimes they’re unavoidable, but I’m not a big fan. However, I generally try not to let dogma guide me, so instead I tried to think of the actual downside of making this method static.
What if I want a behavior where, sometimes, depending on context, DoSomething() doesn’t throw an exception? I still want to verify/validate the parameters, but I just don’t want an exception (maybe I want to log the problem instead, or maybe I have some kind of backup strategy). Well, with a static method, I would have to define another static method and then have the class determine which method to use. It would have to be passed some kind of flag or else read some kind of global state to see which handling strategy was desired. As more verification strategies emerged, this would get increasingly rigid and ugly. That was really all of the justification that I needed–I decided to implement an instance class.
The ‘Finished’ Product
This solution is what I’ve been using lately. I’m hesitant to call it finished because like anything else, I’m always open to improvements. But this has been serving me well.
public class ArgumentValidator
{
public virtual VerifyNonNull(T arg) where T : class
{
VerifyNonNull(arg, "Invalid argument or member.");
}
public virtual VerifyNonNull(T arg, string message) where T : class
{
if(arg == null)
{
throw new ArgumentNullException("MyClass precondition/invariant");
}
}
}
public class MyClass
{
private ArgumentValidator _validator = new ArgumentValidator();
public ArgumentValidator Validator { get { return _validator; } set { _validator = value ?? _validator; } }
public Baz ClassBaz { get; set; }
public void DoSomething(Foo foo, Bar bar)
{
_validator.VerifyNonNull(foo);
_validator.VerifyNonNull(bar);
VerifyOrThrow();
//Get down to business using foo, bar, and baz
}
// This guy validates class invariants
private void VerifyOrThrow()
{
_validator.VerifyNonNull(ClassBaz, "ClassBaz cannot be null!");
}
}
With this scheme, you supply some kind of default validation behavior (and give clients the option to specify an exception message). Here, the default is to throw ArgumentNullException. But you can inherit from ArgumentValidator and do whatever you want. You could have a LoggingValidator that overrides the methods and writes to a log file. You could have an inheritor that throws a different kind of exception or one that supplies some kind of default (maybe creates a new T using Activator). And you can swap all of these in for one another on the fly (or allow clients to do the same, the way MyClass is), allowing context-dependent validation and mocking for test purposes.
Other Ideas
Another thought would be to have IArgumentValidator and a series of implementers. I didn’t choose to go this route, but I see nothing wrong with it whatsoever. I chose the inheritance model because I wanted to be sure there was some default behavior (without resorting to extension methods or other kinds of compiler trickery), but this could also be accomplished with an IArgumentValidator and a default implementer. It just puts a bit more burden on the clients, as they’ll need to know about the interface as well as know which implementation is the default (or, potentially, supply their own).
I’ve also, at times, added more methods to the validator. For instance, in one implementation, I have something called ISelfValidating for entity objects that allows them to express that they have a valid/invalid internal state, through an IsValid property. With that, I added a VerifyValid(ISelfValidating) method signature and threw exceptions on IsValid being false. I’ve also added something that verifies that strings are not null or empty. My only word of caution here would be to avoid making this validator do too much. If it comes down to it, you can group validation responsibilities into multiple kinds of validators with good internal cohesion.