Specification pattern

Specification pattern

The Specification pattern has been added to NGenerics. In my previous post on the Specification Pattern, we explored creating specification functionality using extension methods. It’s actually been implemented with the operator methods (And, Or, Xor) on the actual interface, with an abstract class forming the base of all specifications. The deal-breaker for this approach was the need to add operators |, & and ^ in order to trim down the syntax a little bit. With the Specification Pattern in NGenerics, you can now do this:

public class Customer
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public CustomerStatus Status { get; set; }
    public BalanceStatus BalanceStatus { get; set; }
}

 public enum BalanceStatus
 {
     Settled,
     Owing
 }

public enum CustomerStatus
{
    Bronze,
    Silver,
    Gold
}

public bool ValidateGoldCustomer()
{
    var specification = new PredicateSpecification(x => x.Status == CustomerStatus.Gold)
                .And(x => x.Name == "CustomerName")
                .And(x => x.BalanceStatus ==  BalanceStatus.Settled).Not();

    var testCustomer = new Customer
        {
            Name = "CustomerName",
            Surname = "CustomerSurname",
            Status = CustomerStatus-.Gold
        };
    return specification.IsSatisfiedBy(testCustomer);
}

Alternatively, you can also use the operators defined in AbstractSpecification<T>:

public bool ValidateGoldCustomerWithOperators()
{
    var specification = new PredicateSpecification(x => x.Status == CustomerStatus.Gold) &
        new Predicate(x => x.Name == "CustomerName") &
        !new PredicateSpecification(x => x.BalanceStatus == BalanceStatus.Settled);

    var testCustomer = new Customer
        {
            Name = "CustomerName",
            Surname = "CustomerSurname",
            Status = CustomerStatus.Gold
        };

    return specification.IsSatisfiedBy(testCustomer);
}

The part I’m looking into now is subsumption and partially satisfied specifications. From Martin Fowler and Eric Evans’ paper:

Subsumption allows you to compare specifications to see if satisfying one implies satisfaction of the other. It is also sometimes possible to use subsumption to implement satisfaction. If a candidate object can produce a specification that characterizes it, the testing with a specification then becomes a comparison of similar specifications — removing the coupling of specification mechanism entirely from the domain.

Photo by William Felker on Unsplash


See also