Category name:specification

Specification Pattern Continued

In a previous post, I talked about the specification pattern. In the last sentence I promised you to keep you posted on the next version of the implementation. I still owe you guys that result. So without further ado:

Download it here.

The implementation itself is pretty straightforward. The class has a protected property Predicate that takes in a Lambda expression that results in a boolean ( a predicate). It is protected so that you have to set the predicate in the derived class.

/// <summary>
/// Use the Specification to make some complex (business) logic explicit.
/// </summary>
/// <typeparam name="TEntity">The Type of entity that is the subject of the specification</typeparam>
public abstract class Specification<TEntity>
{

protected Func<TEntity, bool> evalCompiled;
protected Expression<Func<TEntity, bool>> evalExpression;

protected internal Expression<Func<TEntity, bool>> Predicate
{
get
{
return evalExpression;
}
set
{
evalExpression = value;
evalCompiled = evalExpression.Compile();
}
}

/// <summary>
/// Use this method to evaluate the predicate for a single item.
/// </summary>
/// <param name="item">The item to examine</param>
/// <returns>A boolean.</returns>
public bool IsSatisfiedBy(TEntity item)
{
return evalCompiled(item);
}

/// <summary>
/// Use this method to filter IQueryables using the Predicate
/// </summary>
/// <param name="candidates">The IQueryable that needs filtering</param>
/// <returns>An IQueryable that has the added filter</returns>
public IQueryable<TEntity> SatisfyingElementsFrom(IQueryable<TEntity> candidates)
{
return candidates.Where(evalExpression);
}
}

The usage is simple.

Suppose that there is a business rule that big orders need approval by a manager. Big orders are orders above a 1000 euros. There are 2 cases when we need to know whether an order is a big order. First, when the order is created so that we can send a request for approval to the manager and second in a managers app that shows all the big orders.

The class IsBigOrderSpecification is a business rule made explicit. This rule could be throughout your system. Here’s what it looks like:

class IsBigOrderSpecification : Specification<SalesOrderDetail>
{
public IsBigOrderSpecification()
{
Predicate = (o => o.LineTotal >= 1000);
}
}

When a new order is created we can now use this specification to enforce the business rule.

SalesOrderDetail orderLine = new SalesOrderDetail();
orderLine.LineTotal = 999;
bool isBigOrderLine = isBigOrderLineSpec.IsSatisfiedBy(orderLine);
if (isBigOrderLine)
{
Console.WriteLine("LineTotal {0} means this is a big orderline.", orderLine.LineTotal);
}
else
{
Console.WriteLine("LineTotal {0} means this is a not big orderline.", orderLine.LineTotal);
}

Yet the same specification can be used when querying for these big orders in the system. Because it works on IQueryable<SalesOrderDetail> we get all the advantages of deferred execution.

AdventureWorksEntities db = new AdventureWorksEntities();

var query = from so in db.SalesOrderDetails
select so;

var bigOrderLines = isBigOrderLineSpec.SatisfyingElementsFrom(query);

Console.WriteLine("{0} big OrderLines in database", bigOrderLines.Count());

 

Composite specification

In the solution you can also find the code to create composite specifications. Composite specifications are specifications that have been combined. What if we changed the business rule (the manager is getting to busy) to state that only big orders from sales people that have little experience have to be approved. Little experience has been qualified at working at the company less than 2 years. You probably get an IsExperiencedSalesPersonSpecification.

We are now able to combine the 2 specifications as follows:

bool needsApproval = isBigOrderLineSpec.And(new IsExperiencedSalesPersonSpecification().Not()).IsSatisfiedBy(orderLine);

 

My opinion is that this specification pattern is quite powerful in specifying and enforcing business rules in a distributed system.

Specification Pattern Implementation

For some time now I’ve been willing to find a good implementation of the Specification Pattern. Information about this pattern can be found here:

http://en.wikipedia.org/wiki/Specification_pattern

interface ISpecification<TEntity>
{
	bool IsSatisfiedBy(TEntity item);
}

The idea I had was to use the IQueryable of Linq to query over large collections of objects and get all the benefits of delayed execution.

Recently I came across a blog post by Dennis Doomen who  did exactly that. Read about it here:

http://www.dennisdoomen.net/2010/10/my-silverlight-4-reference-architecture_12.html

That implementation gives me:

public class ActiveRegistrationsSpecification
{
	public IQueryable<Registration> SatisfyingElementsFrom
	(IQueryable<registration> registrations)
	{
		return registrations
			.Where(r => r.Status != AgreementStatus.Incomplete);
	}
}

What I ultimately wanted was an implementation that has both capabilities, to evaluate a single item and to get all items from a collection.

Today I found a very old blog post of Nicholas Blumhardt that did that:

http://nblumhardt.com/archives/implementing-the-specification-pattern-via-linq/

public abstract class Specification<T>
{
	public bool IsSatisfiedBy(T item)
	{
		return SatisfyingElementsFrom(new[] { item }.AsQueryable()).Any();
	}

	public abstract IQueryable<T> SatisfyingElementsFrom
	(IQueryable<T> candidates);
}

However this implementation has a downside as Nicholas Blumhardt already states:

“Unknown performance ramifications of AsQueryable() under heavy usage”

And he is right. The AsQueryable() usage is very slow compared to the normal IsSatisfiedBy method.

My idea to improve this implementation was to make the both methods use a Predicate. Of course this wasn’t all that easy, but after some testing I ended up with this very useful implementation:

 

public abstract class Specification<TEntity>
{
	protected Func<TEntity, bool> evalCompiled;
	protected Expression<Func<TEntity, bool>> evalExpression;

	internal Expression<Func<TEntity, bool>> Predicate
	{
		get
		{
			return evalExpression;
		}
		set
		{
			evalExpression = value;
			evalCompiled = evalExpression.Compile();
		}
	}

	public bool IsSatisfiedBy(TEntity item)
	{
		return evalCompiled(item);
	}

	public IQueryable<TEntity> SatisfyingElementsFrom
	(IQueryable<TEntity> candidates)
	{
		return candidates.Where(evalExpression);
	}
}

Next on my wishlist is to get a CompositeSpecification so I can combine specifications with And and Or or Negate a specification. I will keep you posted.