Monday, January 23, 2012

Check -> Argument -> Condition: .NET 4.0 Code Contract, CuttingEdge.Conditions, Shrinkr Check

An early part of designing an effective, maintainable system is consistency. The more consistent your applications responses, the better it will be in the long term. One place that breeds inconsistency in parameter validation, and exception throwing.

So I set out to find a condition checking library capable of accomplishing a few simple goals:

  • Must provide a simple interface for validating conditions (object and state)
  • Must have a consistent response algorithm or structure
  • Must be written in .NET 
  • Must be open-source

With the additional side-goals (or bonus points):

  • A fluent interface
  • Documentation or code samples
  • NuGet package
There are plenty of libraries and source-code examples out there that accomplish these goals:

  • .NET 4.0 Code Contracts - Code Contracts provide a language-agnostic way to express coding assumptions in .NET programs.. The Common Language Runtime (CLR) team is introducing a library to allow programming with contracts in the Microsoft .NET Framework 4. 
  • Shrinkr's Check -  "a Url Shortening Service which demonstrates some of the best practices in developing real life web applications." and contains a fluent checking class structure.
  • CuttingEdge.Conditions - CuttingEdge.Conditions is a library that helps developers to write pre- and postcondition validations in their C# 3.0 and VB.NET 9.0 code base. 
  • GuardQ - validating function arguments.
  • Fluent Validation - "A small validation library for .NET that uses a fluent interface and lambda expressions for building validation rules for your business objects."
  • FluentValidation for .NET 2.0 - Rework of the popular FluentValidation library to work in .NET 2.0. There is one minor syntax change and the LinqBridge (lambda syntax for 2.0) library is required, so please read the docs. Namespaces and licenses are similar to FluentValidation.
Here are a few:

CuttingEdge. Condition Validation Extensions
Conditions is an open-source project (available on CodePlex) that "CuttingEdge.Conditions is a library that helps developers to write pre- and postcondition validations". The library supports a wide-variety of conditions (including those great string based IsNotNullOrEmpty). On the right is a screenshot of the condition validation extensions if you want a quick look.

The library provides a consist way to manage condition checking, and even provides a way to pass a formatted string for the exception message:
Condition.Requires(context, "id").IsNotNull("Parameter {0} cannot be a null reference");

Another feature that this library provides is the WithExceptionOnFailure (AlternativeExceptionCondition WithExceptionOnFailure() where TException : Exception) allowing you to define the exception to be raised when the condition fails. While this is not something you would generally want to do, the added flexibility is certainly appreciated.

.NET 4.0 Code Contracts

.NET Code Contracts is part of the 4.0 version of the .NET framework. From MSDN: "Code contracts provide a way to specify preconditions, postconditions, and object invariants in your code. Preconditions are requirements that must be met when entering a method or property. Postconditions describe expectations at the time the method or property code exits. Object invariants describe the expected state for a class that is in a good state."

It seems intuitive, and easy.

The downside? It requires your application run on .NET 4.0. If your already ugpraded, this seems like a great choice. I mean, it's built into the Framework (no external dependencies ++), and generally offers a comparable offering to other open-source implementations designed to provide this functionality.

Compared side-to-side with Conditions, the syntax and code appear very similar:

            Contract -> Contract.Requires(context != null, "Parameter context cannot be a null reference");
            Condition-> Condition.Requires(context, "context").IsNotNull("Parameter {0} cannot be a null reference");

It's slightly more flexible in it's implementation than Condition. Most notably because Condition has a default set of validations, and exceptions, and Contract is wide open.

As an additional bonus, Code Contracts offer Legacy Requires Statements. From their description it is:

Most code already contains some parameter validation in the form of if-then-throw code. The contract tools recognize if-then-throw statements as preconditions when the statements appear first inside a method, and the entire set of such statements is followed by an explicit Contract method call, such as a Requires, Ensures, EnsuresOnThrow, or EndContractBlock.
When if-then-throw statements appear in this form, the contract tools recognize them as legacy-require statements. The EndContractBlock form is used only if no other contracts follow the if-then-throw sequences, but they should still be tagged as legacy-requires.
Shrinkr's Check.Argument
Shrinkr is "a Url Shortening Service which demonstrates some of the best practices in developing real life web applications." and contains a fluent checking class structure. It's simple, clean and provides a way to validate arguments and provide predicable exception handling.

Here's an example of the Check class. I have also seen a version of this where the Check, Argument classes are not static (from another location):
public static class Check
    public static class Argument
        public static void IsNotNull(object parameter, 
                                     string parameterName)
        { ... }

        public static void IsNotNullOrEmpty(string parameter, 
                                            string parameterName)
        { ... }

 .... etc ....
This provides the basic context that Conditions provides, but is a far simpler implementation. It's also more of a larger project and really out there as a stand-alone library. However, it does meet the goals above, and would be an easy addition to any enterprise's library.

... I still like Conditions the best, but only slightly. Mostly it's the little things, like formatted messages (so I can extract it to a resource) or the validations already built and ready to go.

... There are plenty of options to choose from. Pick one and start using it. Almost all of these will produce better, more consistent results than role-your-own. If your code does not validate add this and get started.

... This is an easy upgrade to your library that will produce good results in the short, middle and long term.

CuttingEdge.Conditions (NuGet)
Fluent Validation
.NET 4.0 Code Contracts on MSDN Magazine
DevLabs Code Contracts
Fluent Validation
FluentValidation for .NET 2.0

No comments: