DDD Step By Step
A Practical Guide to Domain Driven Design

Blogged The Specification Pattern

Blogged The Specification Pattern This page is locked to prevent further edits

Filed under: ,

Continuing our series on Domain Driven Design, we now get to one of the more interesting patterns in DDD – the Specification.

A Specification is, in simple terms, a small piece of logic that sits on it’s own and gives an answer to a simple question … “does this match?”

With a Specification we split the logic of how a selection is made, away from the thing we are selecting.

We have a Customer, and we want to be able check if they are eligible for a discount on a Product.

If we were to put a method on the Customer entity, for example .IsEntitledToDiscountPrice(Product) we start to couple our entities tightly together, and as the number of questions we want to ask of our entity increases, the more polluted its interface becomes.

To avoid this we can use a Specification.

Some Code – A First for the Series

The basic implementation of Specification has a single method .IsSatisifiedBy, in our Discount example above we may have a EligibleForDiscountSpecification, the method would be .IsSatisifiedBy(Customer c)

The actual Specification is variable in how it is defined, but a very simple version for this scenario would be:

public interface ISpecification<T>
{
    bool IsSatisfiedBy(T sut);
}

public class EligibleForDiscountSpecification : ISpecification<Customer>
{
    private readonly Product _product;
    public EligibleForDiscountSpecification(Product product)
    {
        _product = product;
    }

    public bool IsSatisfiedBy(Customer customer)
    {
        return (_product.Price < 100 && customer.CreditRating >= _product.MinimumCreditRating);
    }
}

This now simplifies selection or matching, and the Customer and Product are no longer coupled – our Specification now knows how to decide if the Customer is eligible for a discount. Ignoring the fact that the following is a rotten unit test, we can use our Specification like this:

[Fact]
public void TestSpecification()
{
    var product = new Product() { MinimumCreditRating = 3, Price = 50 };
    var spec = new EligibleForDiscountSpecification(product);
    var goodCustomer = new Customer() { CreditRating = 3 };
    var badCustomer = new Customer() { CreditRating = 1 };

    Assert.True(spec.IsSatisfiedBy(goodCustomer));
    Assert.False(spec.IsSatisfiedBy(badCustomer));
}

Two things become very easy when using Specification – we can easily select from lists and we can pass dependencies without creating coupling.

To find all the Customers in a List<Customer> who are eligible for a discount, we can do (again ignoring the terrible unit test:

[Fact]
public void TestSpecificationCollection()
{
    var minCredit = 3;
    var product = new Product() { MinimumCreditRating = minCredit, Price = 50 };
    var spec = new EligibleForDiscountSpecification(product);

    var customers = new List<Customer>()
                        {
                            new Customer() {CreditRating = minCredit-2}, // bad credit
                            new Customer() {CreditRating = minCredit-1}, // bad credit
                            new Customer() {CreditRating = minCredit} // good credit
                        };
    IEnumerable<Customer> eligible = GetAllCustomersMatching(customers, spec);
    int count = 0;
    foreach (var eligibleCustomer in eligible)
    {
        Assert.True(eligibleCustomer.CreditRating >= minCredit);
        count++;
    }
    Assert.Equal(1, count);
}

public IEnumerable<Customer> GetAllCustomersMatching(IList<Customer> customers, 
ISpecification<Customer> specification) { foreach (var customer in customers) { if (specification.IsSatisfiedBy(customer)) yield return customer; } }

Removing the Dependencies

A scenario I had a while back required an Entity to only allow a method to proceed if a search against a Repository return no matches already there. This specific example turns out to be quite common, people seem to need access to Domain Services or Repositories on a frequent basis.

My first question would be, is the Entity doing too much? Is this an operation that should be in a Domain Service or perhaps a Specification?

Assuming you can legitimately answer “no” to that last question – let us assume that we want to have a Product with a ProductCode – but the ProductCode cannot be duplicated. Leaving aside the fact that this is a rather fake scenario, it means our Product now needs access to the ProductRepository, which is a bit back to front.

What Options Do We Have?

Generally in this scenario we have a few options:

  1. The Entity could call the Repository<Product>.GetByProductCode
  2. The Entity could call a Domain Service to check that it is a unique code
  3. A domain service could hold all the logic and coordinate the Entity  with the Repository.

Option (1) is not a good design – an Entity should not be aware of Repositories. It would probably require a Service Locator pattern to achieve, but becomes very messy very quickly. It could possibly be resolved with Double Dispatch, but is still a bit back to front (see 2 below).

Option (2) is a bit back to front – Entities logically sit behind Domain Services. This could work, as alluded to in a comment to a previous blog post on Domain Services, and if so will require Double Dispatch to be clean.

Option (3) is probably the best of all those options. Domain Services sit in front of Repositories, Entities, and other Domain Services.

The last option not on that list is to use Specification.

If we created a NoOtherMatchingProductCodeSpecification, we can cleanly use this to do the work.

public class NoMatchingProductCodeSpecification : ISpecification<Product>
{
    private readonly IRepository<Product> _repository;
    public NoMatchingProductCodeSpecification(IRepository<Product> repository)
    {
        _repository = repository;
    }

    public bool IsSatisfiedBy(Product product)
    {
        Product match = _repository.GetProductByProductCode(product.ProductCode);
        return match == null;
    }
}

Please bear in mind, this is a contrived scenario, I know this specific example has issues around ACID etc … it is here to prove a point, and Kyle Baley made me write this in a hurry!!!!

What Is Double Dispatch?

So far I have mentioned it more than a few times, and even used it in the title of this blog – so it must be important. You have probably used Double Dispatch many times, even if you didn’t know it had become a pattern with a proper name.

In simple terms, Double Dispatch means we pas in an object to a function, to let the function take an action or make a decision, based on the logic of the passed in object. This decouples our Entities from the actions they take.

Chaining Specifications

It also happens, another useful side effect of Specification is that they can be chained very easily, but I will leave that till a future post. A starting point if you are interested now is on Wikipedia

In Conclusion

I seem to have written more code in this post than I intended, and more than has been the style for the rest of the series. I again intend to blame Kyle for that :) Hopefully it has however given you a more concrete idea of where and how the Specification pattern can be of use.

 

Recent Comments

Leave the first comment for this page.