Implementing the Specification Pattern via Linq
Posted by Nicholas Blumhardt | July 06, 2008 10:23
Linq came with grand promises of bridging the object and relational worlds. Here's one place that it succeeds very well.
Queries and Predicates
Queries have historically sat uneasily alongside predicates in domain-driven designs.
The point of discomfort is that logic needs to be duplicated in different representations for the dual purposes of evaluation an data access.
This is best illustrated by an example - in this case from a library system:
public class Loan
{
// Some details omitted
public DateTime DateBorrowed { get; }
public DateTime? DateReturned { get; set; }
public bool IsOverdue
{
get
{
return DateReturned == null &&
DateTime.Now - DateBorrowed > LoanPeriod;
}
}
}
The IsOverdue property encapsulates some of the logic from our
domain so that it can be utilised within the domain model. Whether or not a loan
is overdue is probably going to be significant in places dealing with the
individual loan - when it is displayed, or when the borrower seeks to renew
their library membership.
Another typical use case for such a system might be an ability to bring up a list of
overdue books. To implement this efficiently, the IsOverdue
predicate needs to be expressed in a form that can select records from the database
(here using NHibernate.Linq):
public class LoanRepository
{
public IEnumerable<Loan> FindOverdueBooks()
{
return from loan in _session.Linq<Loan>()
where loan.DateReturned == null
where DateTime.Now - DateBorrowed > Loan.LoanPeriod
select loan;
}
}
This is obviously simplified, but you can see that even when using Linq it is
still necessary to duplicate the IsOverdue predicate in a form that
can be used to query the database.
In his book Domain Driven Design, Eric Evans discusses a pattern that can come to the rescue, and when implemented using Linq, is better than ever.
Specification
The essence of Specification is that the logic is extracted from the entity into a specification object:
The specification is part of the domain model, but gets used by the data access layer to find matching items.
In this example, the specification is for overdue loans, so it might be represented by an
OverdueLoanSpecification.
Within the domain model, the specification is used as a predicate:
public class Loan
{
public bool IsOverdue
{
get
{
return new OverdueLoanSpecification().IsSatisfiedBy(this);
}
}
}
Within the data access layer, the specification is used as a criterion:
var loanRepository = new LoanRepository(); var specification = new OverdueLoanSpecification(); var overdueLoans = loanRepository.FindBySpecification(specification);
Implementing with Linq
So, how can OverdueLoanSpecification be implemented in a DRY and
optimal manner for both purposes?
The answer turns out to be simple, and is a testament to the incredible elegance of the design of Linq.
First an abstract specification class:
public abstract class Specification<T>
{
public bool IsSatisfiedBy(T item)
{
return SatisfyingElementsFrom(new[] { item }.AsQueryable()).Any();
}
public abstract IQueryable<T> SatisfyingElementsFrom(IQueryable<T> candidates);
}
Implementers only need to define the query-based version - the predicate version is implemented on top of it by the base class.
The OverdueLoanSpecification is part of the domain model:
public class OverdueLoanSpecification : Specification<Loan>
{
public override IQueryable<T> SatisfyingElementsFrom(IQueryable<T> candidates)
{
return from loan in candidates
where loan.DateReturned == null
where DateTime.Now - DateBorrowed > Loan.LoanPeriod
select loan;
}
}
Using a specification within a repository is straightforward, efficient, and preserves all of the lazy-evaluation goodness that Linq brings:
public class Repository<T>
{
public IQueryable<T> FindBySpecification(Specification<T> specification)
{
return specification.SatisfyingElementsFrom(_session.Linq<T>());
}
}
This example captures the essence of the solution, but there are obviously plenty of refinements that should be made in practice. I've started building a more complete an example as part of the Autofac example application - the curious can tinker with a very early version from the Autofac Subversion repository.
(The Autofac example is barely even a skeleton and probably shouldn't be construed as 'best practice' at this stage.)
Advantages
I can see the following advantages of this implementation:
- Logic stays in one place, in the domain model, where it belongs
- Specifications are readily testable even without a database present
- Specifications are composable: chaining two calls to
SatisfyingElementsFrom()will result in only a single database query - Interface bloat can be avoided in both the entity and the repository
Downsides?
- Potential circularity in the entity/specification relationship
- Unknown performance ramifications of
AsQueryable()under heavy usage - A little bit less encapsulation in the entity class
I'll definitely be using this pattern in the future - I'd love to hear of anyone's experiences in using it.
Comments
Posted by Nick | July 06, 2008 01:55
Excellent! Glad this helped :)
Got to love linq
Posted by Luke Marshall | July 07, 2008 01:14
I remember this old problem! Elegant solution! If you're worried about the AsQueryable().Any() hack how about this approach: Instead of abstracting the collection, abstract the individual. public abstract Expression<Func<T, bool>> Satisfy { get; } public Func<T, bool> IsSatisfiedBy { get { return Satisfy.Compile(); } } Now the Repository simply calls public IQueryable<T> FindBySpecification(Specification<T> specification) { return _session.Linq<T>().Where(specification.Satisfy); } The Loan class stays the same. // I hope this comment formats correctly.
Got to love linq - part 2
Posted by Luke Marshall | July 07, 2008 01:45
Taking this further, we could define an InlineSpecification class that allows you to ignore all the implementation details and focus on your query. static public Specification<Loan> IsOverdueSpecification = InlineSpecification.Create<Loan>(x => x.DateBorrowed == null && (DateTime.Now - x.DateBorrowed) > x.LoanPeriod); declaring this member in your Loan class bundles all the logic into one place. The inline class is easy to implement: static public class InlineSpecification { static public Specification<T> Create<T>(Expression<Func<T, bool>> func) { return new Inline<T>() { satisfy = func }; } public class Inline<T> : Specification<T> { public Expression<Func<T, bool>> satisfy; public override Expression<Func<T, bool>> Satisfy { get { return satisfy; } } } }
Posted by Nick | July 07, 2008 02:40
Interesting approach to the expression compilation issue. Neat idea, deserves a post of its own! Nice variation on the inline spec idea too :) I'd discarded this approach because I thought it gave less opportunity for sharing the specification throughout the model. Turns out I was just one static property away from the solution.
Posted by Luke Marshall | July 07, 2008 03:10
Cheers! Ideally you'd want to cache the compiled expression on first use, but I didn't for simplicity. I'm currently having a little play with the expression tree, to see if I can write this: var overdueLoans = loanRepository.Where(x => x.IsOverdue && x.LoanPeriod > TimeSpan.FromDays(5)); Where I replace the x.IsOverdue with the IsOverdueSpecification.Satisfy underneath the covers. I'm sure it's possible (almost cracked it) but I'm not sure if it's hiding too much.
Posted by Nick | July 07, 2008 11:25
Sounds like you're scheming :) How do you propose to get around the ol' "linq queries must be syntactically valid in the first pass"-kind of limitation though? Also - any particular reason to use a static Create method rather than the ctor for InlineSpecification? BTW, I have a strong suspicion that since expressions are immutable, Expression<T>.Compile() is going to cache its results. In fact, expressions known at compile time could probably have their compiled version baked into the assembly. Time to get out Reflector and find out....
Posted by Nick | July 07, 2008 11:47
At first glance it doesn't look like expression compilation is cached - your implementation may be the safe bet, Luke. If Specification accepted the expr in its constructor, subclasses would be about as terse as imaginable: class DueOnDateSpecification : Specification<Loan> { public DueOnDateSpecification(DateTime date) : base(loan => loan.DueDate.Date == date.Date) { } } I don't know that I like cramming this into the base initialiser though. Also - wonder how many DB Linq providers handle DateTime.Date? :)
Dependency Injection
Posted by Jonathan | July 07, 2008 20:21
Would you consider the specifications to be dependencies? Do you see any consequences in calling the constructor on the specifications and working with specific, concrete types rather than working with interfaces that are injected?
Posted by Nick | July 07, 2008 22:00
Hi Jonathan, I would probably call the constructors of the specifications explicitly, since there is going to be a strong binding between the user of the specification and its parameter list. E.g. if using a DueOnDateSpecification, the caller is always going to need to supply exactly one DateTime parameter to the constructor list. I can't see any obvious scenarios where this would be different. Putting DI in between these classes would probably reduce the clarity of the code too much for my liking. As another exercise I've just started thinking about how specifications built in this manner might interact with security, e.g. there may be interesting ways to combine specs such as: repository.FindBySpecification( new DueOnDateSpecification(DateTime.Now), new VisibleToUserSpecification(currentUser)); [The implementation of the Find(params Specification[] specs) version is in the Autofac SVN repo linked above.] Because Linq queries are composable there may be a way to transparently add that second specification, e.g. by adding it to the Find() parameter list using AOP... :)
Shameless Plug
Posted by Luke Marshall | July 08, 2008 01:06
mathgeekcoder.blogspot.com/2008/07/advanced-domain-model-queries-using.html Based on my posts above... I took your ideas and ran in a totally different direction. It's very cool in it's own right, but lacks some elegance of your solution. Cheers!
Posted by Nicholas Blumhardt | July 12, 2008 23:34
Looks good, Luke. Also check out: rabdullin.com/implementing-orm-independent-linq-queries/ and: www.iridescence.no/Posts/Linq-the-Specification-Pattern-and-Encapsulation.aspx for some more cool ideas. (yes, apologies, dear reader - this comment box doesn't accept proper URLs as a very effective but annoying way to prevent spam - promise I'll fix that up soon!)
Your Comment
Disclaimer: These articles represent the opinions of the authors and may not match the official position of Ubik Systems Pty. Ltd. Confirmation should be sought on all matters involving professional advice.

Very nice
Posted by Sean Scally | July 06, 2008 01:40
I was looking for something like this. I had written some code last week that I recognized would be improved by Specification but hadn't gotten around to looking up some .NET implementations of it. Next thing you know, this shows up in my RSS feeds. :) Thanks!