Specification Pattern in Domain Driven Design

Once I implemented Specification but...

  1. It was based on LINQ and IQueryable.
  2. It used single unified Repository (but as for me it's not bad and I think that it's main reason to use Specification).
  3. It used single model for domain and persistant needs (which I think to be bad).

Repository:

public interface IRepository<TEntity> where TEntity : Entity, IAggregateRoot
{
    TEntity Get<TKey>(TKey id);

    TEntity TryGet<TKey>(TKey id);

    void DeleteByKey<TKey>(TKey id);

    void Delete(TEntity entity);

    void Delete(IEnumerable<TEntity> entities);

    IEnumerable<TEntity> List(FilterSpecification<TEntity> specification);

    TEntity Single(FilterSpecification<TEntity> specification);        

    TEntity First(FilterSpecification<TEntity> specification);

    TResult Compute<TResult>(ComputationSpecification<TEntity, TResult> specification);

    IEnumerable<TEntity> ListAll();

    //and some other methods
}

Filter specification:

public abstract class FilterSpecification<TAggregateRoot> where TAggregateRoot : Entity, IAggregateRoot
{

     public abstract IQueryable<TAggregateRoot> Filter(IQueryable<TAggregateRoot> aggregateRoots);

     public static FilterSpecification<TAggregateRoot> CreateByPredicate(Expression<Func<TAggregateRoot, bool>> predicate)
     {
         return new PredicateFilterSpecification<TAggregateRoot>(predicate);
     }      

     public static FilterSpecification<TAggregateRoot> operator &(FilterSpecification<TAggregateRoot> op1, FilterSpecification<TAggregateRoot> op2)
     {
         return new CompositeFilterSpecification<TAggregateRoot>(op1, op2);
     }        

     public static FilterSpecification<TAggregateRoot> CreateDummy()
     {
         return new DummyFilterSpecification<TAggregateRoot>();
     }

}


public class CompositeFilterSpecification<TAggregateRoot> : FilterSpecification<TAggregateRoot> where TAggregateRoot : Entity, IAggregateRoot
{

    private readonly FilterSpecification<TAggregateRoot> _firstOperand;
    private readonly FilterSpecification<TAggregateRoot> _secondOperand;

    public CompositeFilterSpecification(FilterSpecification<TAggregateRoot> firstOperand, FilterSpecification<TAggregateRoot> secondOperand)
    {
        _firstOperand = firstOperand;
        _secondOperand = secondOperand;
    }

    public override IQueryable<TAggregateRoot> Filter(IQueryable<TAggregateRoot> aggregateRoots)
    {
        var operand1Results = _firstOperand.Filter(aggregateRoots);
        return _secondOperand.Filter(operand1Results);
    }
}

public class PredicateFilterSpecification<TAggregateRoot> : FilterSpecification<TAggregateRoot> where TAggregateRoot : Entity, IAggregateRoot
{

    private readonly Expression<Func<TAggregateRoot, bool>> _predicate;

    public PredicateFilterSpecification(Expression<Func<TAggregateRoot, bool>> predicate)
    {
        _predicate = predicate;
    }

    public override IQueryable<TAggregateRoot> Filter(IQueryable<TAggregateRoot> aggregateRoots)
    {
        return aggregateRoots.Where(_predicate);
    }
}

Another kind of specification:

public abstract class ComputationSpecification<TAggregateRoot, TResult> where TAggregateRoot : Entity, IAggregateRoot
{

    public abstract TResult Compute(IQueryable<TAggregateRoot> aggregateRoots);

    public static CompositeComputationSpecification<TAggregateRoot, TResult> operator &(FilterSpecification<TAggregateRoot> op1, ComputationSpecification<TAggregateRoot, TResult> op2)
    {
        return new CompositeComputationSpecification<TAggregateRoot, TResult>(op1, op2);
    }

}

and usages:

OrderRepository.Compute(new MaxInvoiceNumberComputationSpecification()) + 1
PlaceRepository.Single(FilterSpecification<Place>.CreateByPredicate(p => p.Name == placeName));
UnitRepository.Compute(new UnitsAreAvailableForPickingFilterSpecification() & new CheckStockContainsEnoughUnitsOfGivenProductComputatonSpecification(count, product));

Custom implementations may look like

public class CheckUnitsOfGivenProductExistOnPlaceComputationSpecification : ComputationSpecification<Unit, bool>
{
    private readonly Product _product;
    private readonly Place _place;

    public CheckUnitsOfGivenProductExistOnPlaceComputationSpecification(
        Place place,
        Product product)
    {
        _place = place;
        _product = product;
    }

    public override bool Compute(IQueryable<Unit> aggregateRoots)
    {
        return aggregateRoots.Any(unit => unit.Product == _product && unit.Place == _place);
    }
}

Finally, I'm forced to tell that simple Specficiation implementation fits bad according to DDD. You have done great research in this area and it's unlikely that someone proposes something new :). Also, take a look at http://www.sapiensworks.com/blog/ blog.


I think Specification pattern is not designed for query criteria. Actually, the whole concept of DDD is not, either. Consider CQRS if there are plethora of query requirements.

Specification pattern helps develop ubiquitous language, I think it's like kind of a DSL. It declares what to do rather than how to do it. For example, in a ordering context, orders are considered as overdue if it was placed but not paid within 30 minutes. With Specification pattern, your team can talk with a short but unique term: OverdueOrderSpecification. Imagine the discussion below:

case -1

Business people: I want to find out all overdue orders and ...  
Developer: I can do that, it is easy to find all satisfying orders with an overdue order specification and..

case -2

Business people: I want to find out all orders which were placed before 30 minutes and still unpaid...  
Developer: I can do that, it is easy to filter order from tbl_order where placed_at is less that 30minutes before sysdate....

Which one do you prefer?

Usually, we need a DSL handler to parse the dsl, in this case, it may be in the persistence adapter, translates the specification to a query criteria. This dependence (infrastrructure.persistence => domain) does not violates the architecture principal.

class OrderMonitorApplication {
    public void alarm() {
       // The specification pattern keeps the overdue order ubiquitous language in domain
       List<Order> overdueOrders = orderRepository.findBy(new OverdueSpecification());
       for (Order order: overdueOrders) {
           //notify admin
       }
    }
}

class HibernateOrderRepository implements orderRepository {
    public List<Order> findBy(OrderSpecification spec) {
        criteria.le("whenPlaced", spec.placedBefore())//returns sysdate - 30
        criteria.eq("status", spec.status());//returns WAIT_PAYMENT
        return ...
    }
}

I´m late for the party, bug here are my 2 cents...

I did also struggle implementing the specification pattern for exactly the same reasons you described above. If you abandon the requirement for a separate model (Persistence / Domain) then your problem is greatly simplified. you could add another method to the specification to generate the expression tree for the ORM:

public interface ISpecification<T>
{
    bool IsSpecifiedBy(T item);
    Expression<Func<T, bool>> GetPredicate()
}

There is a post from Valdmir Khorikov describing how to do that in detail.

However, I really don´t like have a single model. Like you I find that Peristence model should be kept in the infrastructure layer to not contaminate your domain because of ORM limitations.

Eventually I came up with a solution using a visitor to translate the the domain model to an expression tree of the persistence model.

I recently wrote a series of posts where I explain

  • How to create a Generic specification in C#
  • What is a Visitor Design Pattern and how to make it generic.
  • And my take on how to implement specification pattern in entity framework

The end result becomes very simple to use actually, you´ll need to make the specification Visitable...

public interface IProductSpecification
{
    bool IsSpecifiedBy(Product item);
    TResult Accept<TResult>(IProductSpecificationVisitor<TResult> visitor);
}

Create a SpecificationVisitor to translate the specification to an expression:

public class ProductEFExpressionVisitor : IProductSpecificationVisitor<Expression<Func<EFProduct, bool>>> 
{
    public Expression<Func<EFProduct, bool>> Visit (ProductMatchesCategory spec) 
    {
        var categoryName = spec.Category.CategoryName;
        return ef => ef.Category == categoryName;
    }

    //other specification-specific visit methods
}

There is just some tweeking that needs to be done if you want to create a generic spefication. It´s all detailed in the posts referenced above.