Dave Laribee

Sponsors

The Lounge

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Super Models, Part 1: Sexy Specifications

In Domain-Driven Design we turn to the specification pattern when we want to check whether an object matches some criteria. I think specification is the oft-forgotten bastard child pattern of the domain model pattern language. I know I frequently turn to queries -- sometimes query objects -- when I want to retrieve a set of some entity to work on.

There are some major drawbacks to using queries. Namely there's a huge testing liability. Say we're using a technology like LINQ or NHibernate HQL or even SQL. Well our query and its various predicates that make up our "where clause" are tied up in a single monolithic statement, each of which needs testing. We end up reach deep into the bucket of compromise to find solutions to deal with this mess. Things like object mothers and fluent fixtures help, but are in no way ideal. Wouldn't it be great if we could create a little vocabulary where each word was verified and tested?

Well, yes, it would. And we can accomplish some of these goals by breeding the specification pattern with one of the original GoF patterns, composite. Other people have written about or demonstrated this concept (extensively) so I'll keep my treatment lean and referential, but I'd encourage you to read on; I'll cover a cute little trick at the end.

Sidebar: Specification is quickly challenging service or component for the title "most overloaded term in software development." Think about it; we've got specifications in Behavior-Driven Development, Domain-Driven Design, and Design by Contract. To be clear I'm using specification in terms of model specifications and the practice of DDD.

Composite Specifications

Let's start with a quick interface, and I'm assuming you've done the background reading on the pattern:

public interface ISpecification
{
   bool Matches(T entity);
}

In reality I'd use a generic with a constraint to be sure that "T" in our case is an IEntity. I define an IEntity for my models so I can be sure we have things like an "ID" and a "Version" and can safely but generic constraints in layer supertypes like repositories, builders, factories, etc.

Next I'll define a base class, or layer supertype if you trend fancy, with some special methods and some nested classes. Pay attention to the "And" and "Or" with corresponding nested classes:

public abstract class Specification : ISpecification
{
   public abstract bool Matches(T entity);

   public Specification And(ISpecification specification)
   {
      return new AndSpecification(this, specification);
   }

   public Specification Or(ISpecification specification)
   {
      return new OrSpecification(this, specification);
   }

   private class AndSpecification : Specification
   {
      private readonly ISpecification left;
      private readonly ISpecification right;
      public AndSpecification(ISpecification left, ISpecification right)
      {
         this.left = left;
         this.right = right;
      }
      public override bool Matches(T entity)
      {
         return (left.Matches(entity) && right.Matches(entity));
      }
   }

   private class OrSpecification : Specification
   {
      private readonly ISpecification left;
      private readonly ISpecification right;
      public OrSpecification(ISpecification left, ISpecification right)
      {
         this.left = left;
         this.right = right;
      }
      public override bool Matches(T entity)
      {
         return (left.Matches(entity) || right.Matches(entity));
      }
   }
}

And I suppose we'll make a sample entity and a couple specifications. These are admittedly very anemic (setters are usually work of the devil) and contrived. It's illustrative folks!

public class Customer
{
   public decimal TotalOrders { get; set; }
   public bool Active { get; set; }
}

public class StatusSpecification : Specification
{
   private readonly bool active;
   internal StatusSpecification(bool active)
   {
      this.active = active;
   }
   public override bool Matches(Customer entity)
   {
      return entity.Active == active;
   }
}

public class TotalOrdersSpecification : Specification
{
   private readonly decimal amount;
   internal TotalOrdersSpecification(decimal amount)
   {
      this.amount = amount;
   }
   public override bool Matches(Customer entity)
   {
      return (entity.TotalOrders > amount);
   }
}

With all this in place I can now chain specifications together to achieve a composite -- if not somewhat awkward and noisy -- syntax. Example? Okay, sure:

var specification = 
   new TotalOrdersSpecification(42m).And(new StatusSpecification(true));

var customer1 = new Customer() { Active = false, TotalOrders = 41m};
Console.WriteLine(specification.Matches(customer1));
// False

var customer2 = new Customer() { Active = true, TotalOrders = 43m};
Console.WriteLine(specification.Matches(customer2));
// True
Console.ReadLine();

Bring the Hotness

Update Nigel Sampson describes a similar technique using lamdas and operator overloading. It's a slightly different spin on the same problem, but he also uses the operator overloading trick for clarity. I'd encourage you to check it out; his blog is new but there's some good stuff there already.

I have some issues with the syntax immediately above. Namely we've got a pretty limited means of expressing complex orders of operation in our specifications. If, in pursuit of complex expressions, we pull the AndSpecification and OrSpecification out then we get an even noisier syntax:

var specification = 
    new AndSpecification(..., ...).Or(...);

I think I can do better. If we're pursuing the DDD goal of "the model is the code" and we're trying to bring our model to evermore expressive heights we need to eliminate some of the parenthesis junk. We can do this by using that most magical (and dangerous) feature of C#, operator overloading.

Let's send my specification base class to wardrobe and makeup, stat!

public abstract class SexySpecification : ISpecification
{
   public abstract bool Matches(T entity);

   private class AndSpecification : SexySpecification
   {
      private readonly ISpecification left;
      private readonly ISpecification right;
      public AndSpecification(ISpecification left, ISpecification right)
      {
         this.left = left;
         this.right = right;
      }
      public bool Matches(T entity)
      {
         return (left.Matches(entity) && right.Matches(entity));
      }
   }

   private class OrSpecification : SexySpecification
   {
      private readonly ISpecification left;
      private readonly ISpecification right;
      public OrSpecification(ISpecification left, ISpecification right)
      {
         this.left = left;
         this.right = right;
      }
      public override bool Matches(T entity)
      {
         return (left.Matches(entity) || right.Matches(entity));
      }
   }

   private class NotSpecification : SexySpecification
   {
      private readonly ISpecification specification;
      public NotSpecification(ISpecification specification)
      {
         this.specification = specification;
      }
      public override bool Matches(T entity)
      {
         return !(specification.Matches(entity));
      }
   }

   public static SexySpecification operator &(SexySpecification left, ISpecification right)
   {
      return new AndSpecification(left, right);
   }

   public static SexySpecification operator |(SexySpecification left, ISpecification right)
   {
      return new OrSpecification(left, right);
   }

   public static SexySpecification operator !(SexySpecification specification)
   {
      return new NotSpecification(specification);
   }
}

Now we have a much more natural and terse syntax. You have to use the & and | operators because you can't overload binary operators such as && and ||. I'm OK with this; I get less line noise:

var specification = 
   new TotalOrdersSpecification(42m) & new StatusSpecification(true);

Admittedly it's a little thing, but as we move into more complex composite specifications little differences like these really start to reduce the mental tax associated with parsing a model which, to me, is a big, big deal. And, when all is said and done, isn't it the little things in life that really matter?


Posted 06-15-2008 2:48 PM by Dave Laribee

[Advertisement]

Comments

Colin Jack wrote re: Super Models, Part 1: Sexy Specifications
on 06-15-2008 4:36 PM

Not tried that approach but looks good, definitely gonna give it a shot as I like operator overloading more each time I use it.

Ayende Rahien wrote re: Super Models, Part 1: Sexy Specifications
on 06-15-2008 5:04 PM

That is useful in a very limited sense, mainly because most of the really interesting queries are against persistence storage.

As a simple example, I want to display all the products a user is allowed to buy...

Ryan Gray wrote re: Super Models, Part 1: Sexy Specifications
on 06-15-2008 5:07 PM

You can use a trick to overload && and || :

www.ayende.com/.../7381.aspx

I would have linked directly to Steve's blog, but his site appears to be down for the moment.

Nigel Sampson wrote re: Super Models, Part 1: Sexy Specifications
on 06-15-2008 5:13 PM

I've found you can reduce the building block code by using lamdas.

nichestone.com/.../simplifying_the_composite_specification_pattern.aspx

Normally I wouldn't use predicate specifications in actual code as I've done in the tests as I'd rather create them around business rules. However it does allow us to quickly chain them together.

Dew Droplet – June 15, 2008 | Alvin Ashcraft's Morning Dew wrote Dew Droplet – June 15, 2008 | Alvin Ashcraft's Morning Dew
on 06-15-2008 5:43 PM

Pingback from  Dew Droplet – June 15, 2008 | Alvin Ashcraft's Morning Dew

Avish wrote re: Super Models, Part 1: Sexy Specifications
on 06-15-2008 11:54 PM

To reiterate what Ayende said with a less confident approach: ever since hearing about specifications in your "Fundamental DDD" talk I took a liking to them. However, since most queries are against some sort of non-cached storage, I can't see how they are useful in the common scenario.

Do you mix in some magic ingredient that translates predicate specification into SQL, HQL, LINQ, whatever?

What if they were Expression Tree Specifications rather than Predicate Specifications? Wouldn't that be a little more flexible for translating them into other query interfaces?

Dave Laribee wrote re: Super Models, Part 1: Sexy Specifications
on 06-16-2008 9:56 AM

@Ayende - Yes and no. Specification is useful in deciding when we should apply logic to a particular entity (orthogonal concern to query) but we can also use specifications as building blocks for queries on durable object storage. More to come on that...

Dave Laribee wrote re: Super Models, Part 1: Sexy Specifications
on 06-16-2008 9:57 AM

@Avish - I like that distinction/terminology. I'll be following this with at least two posts re: specifications. One will deal with the query problem.

Dave Laribee wrote re: Super Models, Part 1: Sexy Specifications
on 06-16-2008 10:05 AM

@Nigel - Cool technique. I marked an update linking to your post. Thanks for pointing that out!

Super Models, Part 1: Sexy Specifications wrote Super Models, Part 1: Sexy Specifications
on 06-16-2008 10:57 AM

Pingback from  Super Models, Part 1: Sexy Specifications

Aaron Jensen wrote re: Super Models, Part 1: Sexy Specifications
on 06-16-2008 11:30 AM

FYI, you can enable overriding of the short circuit operators (&& and ||), just override operator true and false. See:

www.blackwasp.co.uk/CSharpLogicalOpOverload.aspx

Arjan`s World » LINKBLOG for June 16, 2008 wrote Arjan`s World » LINKBLOG for June 16, 2008
on 06-16-2008 4:20 PM

Pingback from  Arjan`s World    » LINKBLOG for June 16, 2008

Reflective Perspective - Chris Alcock » The Morning Brew #116 wrote Reflective Perspective - Chris Alcock » The Morning Brew #116
on 06-17-2008 2:48 AM

Pingback from  Reflective Perspective - Chris Alcock  » The Morning Brew #116

Perry Neal wrote re: Super Models, Part 1: Sexy Specifications
on 06-17-2008 11:48 AM

I'm working through this example and trying to "extend" it to make sure I understand it completely.  How would you implement a GreaterThan or LessThan specification?

Dave Laribee wrote re: Super Models, Part 1: Sexy Specifications
on 06-17-2008 8:38 PM

@Perry - You _can_ do that. See Nigel's post (in the update remark above). I'd recommend against it; that's a place where query object or something like the NH criteria API is better suited.

Specifications are domain concepts, IMO. They shouldn't be used to create a generic query language; you'll dilute your domain. Also, as Ayende points out above, you're going to most likely want to query a durable store (i.e. RDBMS).

Richard's Rant wrote Links for Wednesday 17 June 2008
on 06-18-2008 12:06 AM

Well, after a few months of quiet, I am back. Interesting article about Models and Specifications 4 ways

Yoot wrote DDD Specifications
on 06-24-2008 11:22 AM

DDD Specifications

Richard's Rant wrote Links for Tuesday 15 July 2008
on 07-14-2008 6:25 PM

David Cumps has a nice series on Design Patterns Dan Lewis has a post on IE and SharePoint and security

Ollie Riches wrote re: Super Models, Part 1: Sexy Specifications
on 08-04-2008 11:03 AM

Great post and follow up comments

NHibernate « Beautiful code wrote NHibernate « Beautiful code
on 08-06-2008 2:51 AM

Pingback from  NHibernate « Beautiful code

Living in the Tech Avalanche Generation » LINQ To SQL - Going POCO and more…..! wrote Living in the Tech Avalanche Generation » LINQ To SQL - Going POCO and more…..!
on 09-16-2008 9:16 AM

Pingback from  Living in the Tech Avalanche Generation » LINQ To SQL - Going POCO and more…..!

DDD Specifications « Yoot wrote DDD Specifications « Yoot
on 02-23-2009 7:40 PM

Pingback from  DDD Specifications «  Yoot

DDD on the Web wrote Dave Laribee on Sexy Specifications
on 03-03-2009 3:06 AM

In Domain-Driven Design we turn to the specification pattern when we want to check whether an object

DDD on the Web wrote Sexy Specifications by Dave Laribee
on 03-06-2009 6:07 AM

In Domain-Driven Design we turn to the specification pattern when we want to check whether an object

Add a Comment

(required)  
(optional)
(required)  
Remember Me?