Using the Specification Pattern for Querying

The specification pattern is great for adhering to the Single Responsibility Principle (SRP). The reason it can be so powerful is that it encapsulates one piece of logic, and nothing more. I’ve decided to come up with some code that takes advantage of this very easily readable and maintainable code structure.

What Is the Specification Pattern

At the time of writing this, Wikipedia has a pretty good code example for the Specification Pattern in C#. I modified this a bit to use generics so that I can use the pattern with any Entity. Here’s my take:

All of my custom Specifications will derive from the CompositeSpecification. In doing so, whenever I call .And(), .Or(), or .Not() on my object, I’m returning another specification. This allows me to chain them together to create complex business rules that involve several rules that could be nested toegether.

My examples will only use Specifications along with my Customer class, but I could use this same pattern with Orders or LineItems if the need arose.

    public interface ISpecification<T>
    {
        bool IsSatisfiedBy(T candidate);
        ISpecification<T> And(ISpecification<T> other);
        ISpecification<T> Or(ISpecification<T> other);
        ISpecification<T> Not();
    }
    public abstract class CompositeSpecification<T> : ISpecification<T>
    {
        public abstract bool IsSatisfiedBy(T candidate);

        public ISpecification<T> And(ISpecification<T> other)
        {
            return new AndSpecification<T>(this, other);
        }

        public ISpecification<T> Or(ISpecification<T> other)
        {
            return new OrSpecification<T>(this, other);
        }

        public ISpecification<T> Not()
        {
            return new NotSpecification<T>(this);
        }
    }
    public class AndSpecification<T> : CompositeSpecification<T>
    {
        private readonly ISpecification<T> left;
        private readonly ISpecification<T> right;

        public AndSpecification(ISpecification<T> left, ISpecification<T> right)
        {
            this.left = left;
            this.right = right;
        }

        public override bool IsSatisfiedBy(T candidate)
        {
            return left.IsSatisfiedBy(candidate) && right.IsSatisfiedBy(candidate);
        }
    }
    public class OrSpecification<T> : CompositeSpecification<T>
    {
        private readonly ISpecification<T> left;
        private readonly ISpecification<T> right;

        public OrSpecification(ISpecification<T> left, ISpecification<T> right)
        {
            this.left = left;
            this.right = right;
        }

        public override bool IsSatisfiedBy(T candidate)
        {
            return left.IsSatisfiedBy(candidate) || right.IsSatisfiedBy(candidate);
        }
    }
    public class NotSpecification<T> : CompositeSpecification<T>
    {
        private readonly ISpecification<T> other;

        public NotSpecification(ISpecification<T> other)
        {
            this.other = other;
        }

        public override bool IsSatisfiedBy(T candidate)
        {
            return !other.IsSatisfiedBy(candidate);
        }
    }

All of my custom Specifications will derive from the CompositeSpecification. In doing so, whenever I call .And(), .Or(), or .Not() on my object, I’m returning another specification. This allows me to chain them together to create complex business rules that involve several rules that could be nested toegether.

My examples will only use Specifications along with my Customer class, but I could use this same pattern with Orders or LineItems if the need arose.

Types of Specifications

In these examples, I’ve created some customer specifications so that I can query my Customers based on the criteria that the business has set aside as the rules for defining Customer status. I have a Preferred Customer, Gold Customer and Platinum Customer. With these specifications in place, we can even extend our Customer class (with or without extension methods) to determine if they fit the criteria. Again, this keeps our code in one place, so any changes won’t need to be duplicated across the project.

    public Customer
    {
        public bool IsPreferredCustomer()
        {
            return new PreferredCustomerSpecification().IsSatisfiedBy(this);
        }
    }

I probably wouldn’t add this property unless it was needed, but it shows how to keep your business logic for determining a preferred customer in one place.

The customer status specifications are based on inheritance. You have to meet the previous criteria AND meet some new criteria to be satisfied by the next “tier”. These are fairly standard and have the benefit of being easy to write and be very expressive, but have the drawback of being quite inflexible. The other specification in my examples that is a Hard Coded Specification (as seen in Martin Fowler’s Specifications paper) is the BadCustomerSpecification.

    public class BadCustomerSpecification : CompositeSpecification<Customer>
    {
        public override bool IsSatisfiedBy(Customer entity)
        {
            return (entity.AccountCredit < 0m);
        }
    }

The SuspiciousCustomerSpecification is a parameterized specification. This can allow for a bit more flexibility than a hard coded specification since you’re able to pass in some data or objects. While this is a bit more flexible, it still requires special purpose classes.

    public class SuspiciousCustomerSpecification : CompositeSpecification<Customer>
    {
        private readonly IEnumerable<long> suspiciousCustomerIDs;

        public SuspiciousCustomerSpecification(IEnumerable<long> suspiciousCustomerIDs)
        {
            this.suspiciousCustomerIDs = suspiciousCustomerIDs;
        }

        public override bool IsSatisfiedBy(Customer entity)
        {
            return suspiciousCustomerIDs.Contains(entity.ID);
        }
    }

In the SuspiciousCustomerSpecification we can pass in a list of customers that have been flagged due to activity, or other reasons.

More Thoughts on Specification Querying

While these examples are a bit more advanced that the typical specification which with I’ve dealt. There is much, much more that you can do with this design pattern. It’s important to understand that you shouldn’t implement a pattern just to do so, use them when the situation fits the pattern that is evolving from the problems you’re facing. Specifications should adhere to a single rule that matches user voice.

If you can’t describe it in the user’s language, you should stop and think about whether or not you’re over engineering.

and…

Staying in user voice makes it easier to ask a user how something in the system SHOULD behave, when you are unsure.

These two quotes are from a blog post by Lee Brandt at Codebucket.com and I they are imperative to creating specifications.

Related:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Chris Missal

Oh hey, I'm a Senior Consultant for Headspring in Austin, TX. I've been working in software professionally since 2006 and I really, really love it. I'm mostly in the Microsoft world, but enjoy building computer things of all sorts (to be vague). When I'm not slinging code, I'm probably out and about slinging discs, bowling balls, or good beer with great friends.
This entry was posted in Design Patterns, Design Principles, DRY, SOLID. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Mike

    You can take this further and have your Spec return Expression> and then you can use the specifications with linq quiries or linq to nhibernate.

    The question I have is if you have a service layer call your repository and pass it a specification how do you verify in tests that your service layer calls the repository with the correct specification?

  • http://www.mostlyclean.com Steve Burman
  • http://www.cihataltuntas.com Cihat

    @Chris,@Mike
    Without LINQ Could you use these specifications to Query database?If so can you give me a example and strategies to fallow.

  • http://jonathan-oliver.blogspot.com Jonathan

    We’ve been using an “operator overloaded” variant of the Specification Pattern that doesn’t require all of the ugly (And/Or)Specification classes:

    http://compiledexperience.com/blog/posts/Simplifying-the-Composite-Specification-Pattern

    Further, Nicholas Blumhardt (creator of Autofac & MEF developer) talked about using the Specification Pattern with LINQ to query NHibernate:

    http://ubik.com.au/article/named/implementing_the_specification_pattern_with_linq

  • http://timbarcz.devlicio.us Tim Barcz

    @Jonathan

    IMO Operator Overloading is NOT a good idea….

    far uglier is that than And/Or

  • http://blogs.windowsclient.net/vborovikov/default.aspx Vladislav Borovikov

    @Cihat:

    You can consider this composite specification as an abstract syntax tree that is then translated into plain SQL expression for WHERE clause. Translating the tree is usually implemented using Visitor pattern.

  • http://thelimberlambda.com/ Eric Smith

    The code that you’ve posted appears not to be quite right; in particular,

    Within CompositeSpecification, the methods that currently read:

    public ISpecification [And|Or|Not](ISpecification other)

    should read:

    public ISpecification [And|Or|Not](ISpecification other)

  • http://www.lostechies.com/members/chrismissal/default.aspx Chris Missal

    @Eric

    Thanks, it’s fixed now.

  • http://www.markdavidrogers.com Mark Rogers

    I like your improvements on the wikipedia article’s version. Nice Job!

  • indiecodemonkey

    is there a way to get the code for this so it’s readable? right now, using Firefox or IE, the code font is huge and the right side gets lopped off…

    • Anonymous

      Somewhat fixed, not 100%, but better until I can look into it a bit more.

  • http://www.domain-hosting-services.in/ domain and hosting

    You have done a great job in this post and great improvement on Wikipedia article’s.

  • http://www.mactonweb.com web development bangalore

    Great improvement on Wikipedia article’s.And you have done a great job.

  • http://www.mactonweb.com Web design London

    I have is if you have a service layer call your repository and pass it a specification how do you verify in tests that your service layer calls .

  • http://www.best-hostings.in/ Best Hosting

    Thanks for providing the queries. Those are really helpful to us.

  • http://www.seo-forum.in/ best seo forums

    Good information included in this post. Its really interesting to make a look into it. 

  • http://www.webhostings.in/ Indian web hosting company

    A very good and informative article indeed . It helps me a lot to enhance my knowledge, I really like the way the writer presented his views.I get clear on this programming. Nice one.