var blog = new ThoughtStream(me); RSS 2.0
 Thursday, June 19, 2008

Inspired by my recent readings in Domain Driven Design - specifically Chapter 10, "Supple Design" - and recent posts by David Laribee and Nigel Sampson, in combination with the recent pains I've been putting myself through, trying to test query generation code in a search screen, I decided to spike out a quick example of a reusable Specification implementation.

Rather than repeat what's already been said, I'm just going to get straight to the code.

using System;
 
namespace Spec_Spike
{
    class Program
    {
        static void Main()
        {
        
            Foo foo1 = new Foo();
            foo1.Bar = "Test";
            
            ISpecification<Foo> equalSpec = new Specification<Foo>(foo => foo.Bar == "Test");
            ISpecification<Foo> notEqualSpec = new Specification<Foo>(foo => foo.Bar != "Not Equal To This Text");
            ISpecification<Foo> falseSpec = new Specification<Foo>(foo => false);
 
            ISpecification<Foo> passingSpec = equalSpec.And(notEqualSpec);
            ISpecification<Foo> failingSpec = passingSpec.And(falseSpec);
 
            Console.WriteLine(equalSpec.IsSatisfiedBy(foo1));
            Console.WriteLine(notEqualSpec.IsSatisfiedBy(foo1));
            Console.WriteLine(passingSpec.IsSatisfiedBy(foo1));
            Console.WriteLine(failingSpec.IsSatisfiedBy(foo1));
        }
        
    }
    
    public class Foo
    {
        public string Bar;
    }
    
    
    public interface ISpecification<t>
    {
        bool IsSatisfiedBy(t obj);
        ISpecification<t> And(ISpecification<t> lhs);
    }
    
    public class Specification<t>: ISpecification<t>
    {
        private readonly Predicate<t> _pred;
 
        public Specification(Predicate<t> pred)
        {
            _pred = pred;
        }
 
        protected Specification(){}
    
        public virtual bool IsSatisfiedBy(t obj)
        {
            return _pred(obj);
        }
 
        public ISpecification<t> And(ISpecification<t> andSpec)
        {
            return new AndSpecification<t>(this, andSpec);
        }
    }
    
    public class AndSpecification<t>: Specification<t>
    {
        private readonly ISpecification<t> _spec1;
        private readonly ISpecification<t> _spec;
 
        public AndSpecification(ISpecification<t> spec1, ISpecification<t> spec)
        {
            _spec1 = spec1;
            _spec = spec;
        }
 
        public override bool IsSatisfiedBy(t obj)
        {
            return (_spec.IsSatisfiedBy(obj) && _spec1.IsSatisfiedBy(obj));
        }
 
    }
    
}

Drop this code into a console app in C# 3.5 and watch the magic happen. Here's the output:

image

These are the results that I expected - the first 2 individual specs passed, the first combined spec passed, and the last combined spec failed.

Overall, I'm fairly excited about the possibilities here. I'm thinking that I may actually be able to properly unit test the query generating code in my search screen with this basic technique. I'm still not 100% sure on that, but I plan on trying, anyway.

For more information on the Specification pattern, I highly recommend you read the previously linked posts by David Laribee and Nigel Sampson, in addition to reading all of the Domain Driven Design Book. This is one of those books that should fundamentally change the way you think about software development.

Navigation
About Me
View Derick Bailey's profile on LinkedIn

Send mail to the author(s) Contact Me
Archive
<June 2008>
SunMonTueWedThuFriSat
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2008
Derick Bailey
Sign In
Statistics
Total Posts: 91
This Year: 91
This Month: 0
This Week: 0
Comments: 40
Themes
Pick a theme:
All Content © 2008, Derick Bailey
DasBlog theme 'Business' created by Christoph De Baene (delarou)