Devlico.Us
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @devlicious

Jeff Perrin - Sexier Than You Are



The Specification Pattern

Hot on the heels of my devastatingly fantastic post on an implementation of the Snapshot Pattern, I give you my next piece du resistance. In this little post, I'd like to delve into the Specification Pattern.

So what the heck is it? Matt Berther provided a pretty good introduction where he states:

It's primary use is to select a subset of objects based on some criteria...

That pretty much sums it up. What we want to do is extract out a specification for a subset of objects we might be interested in. We do this by creating specification objects.

You'll see something like this in a lot of applications:

This is fine in small doses, but your definition of a highly priced sale product might change over time, and we want to avoid having our logic for what IsOnSale and what a highly priced object actually is sprinkled throughout our code. One way to avoid this is to extract our logic into a Specification object like so:

Now the first loop I wrote can be written like so:

This is a slight improvement... There's actually more code to write, but now we can separately unit test each specification we create, without worrying about the loop:

Ok, so that's interesting, but we haven't even gone halfway, here. Why don't we refine that loop I wrote to use the new Generic collections in .NET 2.0:

Wow, now there's some serious savings on lines of code. "But you're missing the bit about the high priced products from the first example!?!" I hear you saying. Fear not, let's extract that into another specification like so:

We're still left with one problem, though. How do we tell the generic list of all products that we want the products that are both on sale and over a certain price? Let's try extracting our functionality into a Specification superclass first. This is what our ProductOnSaleSpecification and ProductPriceGreaterThanSpecification will inherit from. Once that's over with, we can create a CompositeSpecification, which is abstract, and allows us to pass in the left and right sides of a specification "equation." We can then implement yet another subclass (this time of CompositeSpecification) that we'll call AndSpecification. Here it is:

Now our original loop that looks for highly priced products that are on sale looks like this:

We're getting there, but we're still not done. The code we just wrote is soooo .NET 1.1. Let's get fluent with our interfaces and add some sweet sugar to our Specification base class...

I've just added some convenience methods to Specification that will let us chain together any specifications we create. Therefore, our original loop ascends to a new level of sexiness...

For the "slow" ones in the class I've put up a pretty picture for you to look at, while the rest of the class downloads the code, complete with unit tests.

kick it on DotNetKicks.com



Comments

Joey Beninghove said:

Ahh, yes.  The specification patter is proving very useful for me these days as well.  And the syntax you were able to create with the composite specification is very elegant.  Nice to see someone else really care about code craftsmanship.  

I also like to use simple specifications for reusable bits of validation logic as well.  Like validating empty strings, dates, string lengths, numerics and any other validation I have to do in more than one place (DRY).  

Looking forward to getting my Nilsson DDD book next week...  :)

# December 13, 2006 10:45 PM

Rob Eisenberg said:

Jeff,

Nice post.  I particularly liked the fluent interface addition at the end.

# December 14, 2006 9:23 AM

Jeff Perrin said:

Thanks, guys.  To be fair, the fluent interface stuff is nothing new... we've been using a Java version of this code at work for several months now, and I've seen ruby versions as well.  All I've done is convert the pattern to C# utilizing all the new .NET 2.0 stuff (generics, collections accepting predicates, etc).

# December 14, 2006 11:45 AM

Billy McCafferty said:

Nice summary Jeff...you'd probably enjoy taking a look at my 2nd refactoring challenge:  http://devlicio.us/blogs/billy_mccafferty/archive/2006/11/23/refactor-it-challenge-2.aspx.  The main challenge was to refactor the code to the specification pattern.  The specification/interpreter pattern is definitely one of my favorites in the realm of useful patterns.

# December 14, 2006 12:31 PM

Jaakko Haapasalo said:

As an aside, the specification classes are called predicates in C++. This is a pretty common pattern in the C++ STL. Composing the specifications is neat, although wouldn't it be nice if we didn't have to implement propositional logic operators yet again...

# December 14, 2006 12:36 PM

Jeff Perrin said:

Jaakko,

They're still "called" predicates in C#...

http://msdn2.microsoft.com/en-us/library/bfcke1bz.aspx

Basically, the IsSatisfiedBy method is the predicate in this instance. What the heck does "implement propositional logic operators yet again" mean? I'm curious.

# December 14, 2006 3:42 PM

someone said:

How is this different than using the predicate delegate and anonymous delegates?:

productList.FilterBy(delegate(Product p) {

   return p.Price > 100.0;

});

If you want to reuse them just place them on a static class.

static class ProductUtilities

{

   static bool IsExpensive(Product p) { return p.Price > 100.0; }

   ...

}

And they can also be chained:

productList.FilterBy(delegate(Product p) {

   return ProductUtilities.IsExpensive(p) &&

       ProductUtilities.IsOnSale(p);

});

In comparison your code feels soo Java-like.

# December 14, 2006 8:29 PM

Matt Berther said:

Jeff,

Thanks for the link.

I really like what you've done with this pattern, especially the fluent interface at the end. I will definately have to find a way to work this into my own stuff.

# December 14, 2006 9:16 PM

Jeff Perrin said:

Someone,

I wrote about the exact method you specify here:

http://www.jeffperrin.com/index.php/2006/06/28/specification-pattern-with-predicates/

After mulling it over for a while, I realized I hated the idea of having a static class full of specification methods. You're right that the code from this article looks "Java-like" (except for the fact that we're passing a freaking method to an object), but the alternative is the messy looking anonymous delegate syntax in C# 2.0. When 3.0 arrives, *then* we'll talk. ;)

# December 15, 2006 10:26 AM

TrackBack said:

# December 16, 2006 4:56 PM

Gary said:

I've been using the Specification pattern for a while now (very similar to what you have) and it works a treat [cuts the amount of code I have to write.. always a good thing!!!].

Just a couple of differences between what we have:

1) NotSpecification<T> is derived directly from Specification<T> and not CompositeSpecification<T>, I just use :

public bool IsSatisifedBy(T candidate)

{

return !m_wrapped.IsSatisfiedBy(candidate);

}

2) On the abstract Specification I expose a method:

public IList<T> Filter(IList<T> candidates)

{

return new List<T>(candidates).FindAll(isSatisfiedBy);

}

(whether this is a good or a bad decision, I will let you decide)

# December 18, 2006 8:57 PM

Jeff Perrin :: Jump the Fence or Walk Around » Blog Archive » What I Learned From X That Makes Me a Better Programmer in Y said:

Pingback from  Jeff Perrin :: Jump the Fence or Walk Around  &raquo; Blog Archive   &raquo; What I Learned From X That Makes Me a Better Programmer in Y

# October 3, 2007 11:46 PM

Reshef’s tip of the day » Blog Archive » The Specification Pattern said:

Pingback from  Reshef&#8217;s tip of the day  &raquo; Blog Archive   &raquo; The Specification Pattern

# December 5, 2007 3:38 AM

Your Daily Mark.Net said:

The last couple of days I&#39;m learning a lot about the specification pattern. These links can helped

# January 11, 2008 2:02 AM

Specification Pattern and Lambdas « Ang3lFir3 - Life as a Code Poet said:

Pingback from  Specification Pattern and Lambdas &laquo; Ang3lFir3 - Life as a Code Poet

# July 29, 2008 1:51 AM

specification pattern for selection on lists at dpdk Open Source said:

Pingback from  specification pattern for selection on lists at dpdk Open Source

# September 10, 2008 11:03 AM

Jeff Perrin :: JeffPerrin.com » Blog Archive » What I Learned From X That Makes Me a Better Programmer in Y said:

Pingback from  Jeff Perrin :: JeffPerrin.com  &raquo; Blog Archive   &raquo; What I Learned From X That Makes Me a Better Programmer in Y

# October 12, 2008 10:21 AM

About Jeff Perrin

Jeff is not an internationally (or even locally) known expert in anything related to software development. He holds no certifications worth speaking about, and didn't graduate from University. The value of anything written on his blog should be deemed suspect at the minimum, and blatantly false and misleading in the worst case. Don't let his innate sex appeal fool you... Jeff does not know anything about which he speaks. Check out Devlicio.us!

Our Sponsors

Red-Gate!

Proudly Partnered With