Declarative state of mind


Over the years, we have seen C# language evolve into a more dynamic language, and also have seen numerous frameworks and APIs out there implementing a more declarative style. Famous example would be LINQ, and one can appreciate how the language flows and how readable it is. For too many years we have programmed in a procedural manner, and we have forgotten who the target audience for our code is…..yes the audience is us, the programmers!!!!

Procedural code can be hard to read, which makes code hard to maintain. To be declarative is to write code in a way that declares your intention fluidly using fluent interfaces. I’ve come up with an example that illustrates this.

In methods, it’s very common to write guard conditions against method parameters, be it value types or reference types. An example below illustrates this.

public double Divide(int top, int bottom)
{
    if (bottom == 0)
    {
        throw new MyBusinessException("Cannot divide by zero");
    }
    return top / bottom;
}

You may be thinking, why don’t we just let .NET throw a DivideByZeroException. I tend to disagree with this approach, because I feel that it is much more appropriate for an application to throw and handle it’s own category of exceptions….but that in itself is another can of worms. 🙂

If you have lots of parameters, and you have to guard against them, and these checks get pretty large very quickly, which makes it hard to read. Of course if you’re developing in .NET 4, there’s Code Contracts, but if you’re not, here’s my version of making it declarative.

public double Divide(int top, int bottom)
{
    Verify.ThatValue(bottom).WhenEqualsTo(0).WillThrowException<MyBusinessException>("Cannot divide by zero");
    return top / bottom;
}

I’ve created a Verify library for this purpose, and it understands reference and value types. The fluency with the method chaining allows one to easily understand what that line of code is doing, somewhat like reading a sentence….Verify that the value ‘bottom’, when equals to zero will throw a MyBusinessException with message “Cannot divide by zero”.

Here’s another example. When someClass is null, we write a warning to Trace, and throw an exception.

public void SomeMethod(SomeClass someClass)
{
    Verify.ThatClass(someClass).WhenIsNull()
        .WillExecuteAction(() => Trace.TraceWarning("some class is null"))
        .WillThrowException<MyBusinessException>("some class is null");
    // do something here.
}

There are quite a number of useful checks, and here’s the interface for Verify for reference type.

public interface IVerifyClassCondition<T> where T : class
{
    IVerifyExceptionThrower WhenIsNull();

    IVerifyExceptionThrower WhenIsNotNull();

    IVerifyExceptionThrower WhenEqualTo(T obj);

    IVerifyExceptionThrower WhenNotEqualTo(T obj);

    IVerifyExceptionThrower WhenMeetsCondition(Func<T, bool> condition);
}

Here’s the interface for Verify for value types.

public interface IVerifyStructCondition<T>  where T : struct, IComparable<T>, IEquatable<T>
{

    IVerifyExceptionThrower WhenGreaterThan(T obj);

    IVerifyExceptionThrower WhenLessThan(T obj);

    IVerifyExceptionThrower WhenEqualsTo(T obj);

    IVerifyExceptionThrower WhenNotEqualsTo(T obj);

    IVerifyExceptionThrower WhenGreaterThanEqualTo(T obj);

    IVerifyExceptionThrower WhenLessThanEqualTo(T obj);

    IVerifyExceptionThrower WhenIsDefault();

    IVerifyExceptionThrower WhenIsNotDefault();

    IVerifyExceptionThrower WhenMeetsCondition(Func<T, bool> condition);
}

I guess you get the idea. It’s simple and straightforward, but how often do we bother to write fluent interfaces like this…..I hope this has helped you gain a new appreciation for declarative style and it’s readability. You can download the sample solution below, and I’ve included a whole bunch of unit tests.

Download this library for VS 2010 here.

Download this library for VS 2008 here. (I modified the csproj and solution files from vs2010, hope it works)

Share this post :
Advertisements
Posted in C#. Tags: . Leave a Comment »

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: