Is the Specification Pattern obsolete?

I’m a guy who loves many of the new patterns that I get to know. But sometimes when I show that pattern to colleagues around me, they tilt their heads and say: „Arrrm, who needs this?“. Often they help me to get back to the ground and think again about intents and benefits of one or the other pattern.

Currently I’m rethinking the Specification Pattern, which has been introduced by Eric Evans and Martin Fowler some time ago and got some attention in the DDD community and beyond. The intent of the Specification Pattern is to separate the logic for (e.g.) filtering an entity from the entity itself. This responsibility is encapsulated in single classes – the specifications. Those specifications are given for example to a single method Filter() on a repository, which takes care of filtering the domain model by the specifications. Thus, you bypass the need for having several special methods in your repository which take care of the actual filter operation (such as FilterByCustomerName(), FilterByCustomerAddress() etc.).

An example interface snippet for a repository of persons with a specification filter method could then be:

interface IPersonRepository
{
    IEnumerable<Person> Filter(ISpecification<Person> filterTerm);
    // ...
}

Summarized, some key benefits of the Specification Pattern are:

  • Loose coupling of the filter logic from the objects being filtered,
  • Single responsibility: Interface of repository/data provider isn’t polluted with lots of filter methods,
  • Callers can express in a flexible way by which criteria entities can be filtered,
  • Composition of specifications (e.g. by a fluent interface) yields to flexible filter queries, for example:
    [sourcecode language=’c#‘]var filter = Filter.By(25).And(„Frankfurt“)[/sourcecode]

But now the provocative question that one could come with: Who needs the Specification Pattern in times of C# 3.0 and Expressions? This might sound disturbing at first, but let me explain…
C# 3.0 came up with the new concept of Expressions/Expression trees. This way, code can be treated as a kind of syntax tree in the program. Developers can extend the tree with additional code portions and then compile it into executable code which can be invoked.

Therefore Expressions seem to give us similar benefits for filtering as specifications do. By using Expressions, we are able to define a single Filter() method on the repository, which gets an appropriate Expression as argument. Consumers of the repository can call this method with their custom filter Expressions and thus we’ve got the same benefits: loose coupling of filter logic and objects to be filtered, flexibility for callers to provide custom filter criteria and the possibility to combine several filter criteria (several Expressions).
One could argue that with specifications we’ve got better encapsulation of the filter logic into separate classes. But this can be done with Expressions as well (e.g. by separate wrapper classes or dedicated Expression providers), so that isn’t a good argument…

The interface of a repository of persons with a filter that uses Expressions might look like this:

interface IPersonRepository
{
    IEnumerable<Person> Filter(Expression<Predicate<Person>> filterTerm);
    // ...
}

This leads again to the question: Do we still need the Specification Pattern or is it already embedded with Expressions in the language (C# 3.0) itself?

Pattern focus

First I want to mention that the intent of a pattern is not (only) to provide a technical solution, but also a conceptual guideline for a problem at hand. Thus Expressions as technical solution don’t cover the intent of the Specification Pattern. The Specification Pattern can be implemented with the help of Expressions, but that’s another point. So, directly comparing the Specification Pattern with Expressions is like an apple-pear-comparison.

Encapsulation focus

Let’s come to use cases when I would prefer the use of dedicated specification classes rather than directly using Expressions.
First as a team lead you could want to enforce the use of dedicated specification classes in your development team (thus enforce encapsulation of the filter logic). By giving Expressions or Predicates to filter methods directly,  developers would be allowed to define filter expressions whereever they want to. You don’t have the control over this process and please don’t trust your project guidelines: If developers are allowed to do something wrong, they will do.

With specifications you can force your team members to write specification classes for their requirements, which leads to enforced encapsulation. Furthermore you drive reuse of existing specification classes. Other developers are encouraged to use existing specifications, especially because of the additional effort for writing new specifications. By combining several specifications, the reusability aspect is pushed even more.

Domain model focus

Giving consumers the full flexibility of defining custom filter criteria with specifications can be very handsome in many situations. However, in other scenarios instead of giving full flexibility, you may want to restrict the set of filters for your domain model. If you focus on your domain, you perhaps want a restricted set of specifications, each with a very specific meaning in your domain! Binding such specifications to your domain model makes the purpose of your domain and how it can/should be used in terms of filtering much clearer.

Technically, in order to restrict access to a particular set of specifications, you could create sealed specification classes inside of your domain model services (same layer as repository). Consumers of the repository would be allowed to call the Filter() method on the repository with those specifications (and compositions of those), but they would not be able to create new specifications if you don’t mark the specification interface as public. This way you get two characteristics: Restricted filtering, which fits into your domain and your use cases on the one hand, and encapsulation/separation of filter logic and entities which should be filtered on the other hand.

Bottom line

This article started with an interesting and provocative question: Is the Specification Pattern obsolete? This question came up with a look at Expressions in C# 3.0. Technically you can achieve similar results when using Expressions instead of implementing the Specification classes by hand. But as the last sections have shown, in my opinion the Specification Pattern is not obsolete! As pattern it’s adding very specific value to the plain technical solution, when you take encapsulation and domains into account. Then it clearly goes beyond the technical aspect which many developers see at first sight.

Those are my current thoughts on specifications, but of course my opinions are not carved in stone. What do you think? What points I’ve missed perhaps? I’m eager for your comments!

kick it on DotNetKicks.com

5 Gedanken zu „Is the Specification Pattern obsolete?“

  1. I don’t think it’s obsolete, all you really have to do it make a slight change in the interface.

    Rather than saying:

    interface ISpecification {
    bool IsSatisfiedBy(T candidate);
    }

    Simply change the interface to:

    interface IExpSpecification {
    Expression<Func> Predicate { get; }
    }

    Personally, I’m not to keen on the name specification as I pretty much have to explain that I’m talking about are filters.

  2. Perhaps filters, perhaps not. Specifications could be used for more than filtering (validation etc.). Therefore I personally like the name specification, because it clarifies the intent: specifying some characteristic on the domain model.

    There is no mistaking that you could use Expressions to implement the Specification Pattern on the technical side. But that was not the question and it’s not answering the obsolete concern (btw: In my opinion this doesn’t add any value in nearly all situations in comparison to implementing the Specification Pattern by hand).

    To straighten things out again: As you can see with my „focus“ sections, the Specification Pattern is not obsolete for me, because it still has an important value. I’ve inserted some bottom line, thanks for the comment!

  3. My personal „default“ opinion in this matter is: One can view expressions/expression trees as incarnations of the pattern, thus the pattern is more valid than ever, yet it doesn’t need a dedicated additional implementation (by default). And I don’t like the idea of replacing some core feature for minor gains.

    However, there are reasons why you still may want an implementation on top of C# expressions. You named some of them, but I’d like to broaden the topic somewhat: Essentially the specification pattern is a special (and rather limited) incarnation of a DSL. And thus, the usual reasons for coming up with a DSL should apply here:
    – raising the level of abstraction. This would gain more efficint development (say RAD style) or open „programability“ to new audiences, such as power users.
    – Restricting the feature set (i.e. only allowing certain operations, e.g. only those that make sense in a certain context).
    – configuration/customization over implementation.
    – other reasons, like being able to trace and time the execution, offloading workload to other machines, etc.

    Personally I have used „specifications“ (I don’t like the name either) in two situations where expression trees wouldn’t have helped anyway:
    – When I needed a trimmed down „rules engine“
    , i.e. some kind of configurable expressions. This is usually the case when these conditions change often or have to be changed by non-developers or on the fly (i.e. without compiling).
    – When the application needed end user defined logic, espessially user defined queries, including the ability to edit, store, and execute those queries.

    Regarding this post in general: The specification pattern is just one of many patterns that was conceived during the OO heydays. But other approaches, like components, meta programming, functional programming, and the general evolution of the platforms have had an effect and while OO may still be a cornerstone of todays development, it is no longer the sole characteristic. Thus today any pattern from that „early“ time may seem questionable at first glance. At second glance it may simply have to be adapted to a changed environment, it may be obsoleted by some competing pattern, or it may be superseded by some broader notion. Bottom line: It’s good to ask these questions, and to question „established knowledge“, as it will at least foster a better understanding, and possibly lead to new, better ideas. Thus good work.

  4. I also agree with your „Bottom Line“ conclusions. The relevance of the pattern, particularly in DDD, is to help in creating a common language to be shared between developers and domain experts. The fact that LINQ and C# Expressions allow us to implement similar functionality is actually a validation of the pattern and its usefulness.

    Thanks for the post!

  5. I just stumbled over this article, when trying to find so useful ressources about this topic.

    Actually I think you only looked into one aspect of specification: predicates and how to use them. It looks like the ‚criteria’+’criterion‘ for ‚repository pattern‘ is nearly the same 🙂 and works easily with expressions.

    But: They become difficult, if you query a very big database table and dont want to check every possible entry after it came from th database.

    I think there is a big advantage in the other part of specification and this is where you scratched the surface at the end: Naming concepts in the domain model.

    I usually have logic describing rules of the domain in services or domain objects, which bubble in refactoring phases into the service for the entity, because I didnt know where to put them. Having a concrete object for them, which occurs in controllers, domain objects and services and says: hey, here this one specification is important. This makes a clear message.

    I am not a fan of th predicates logic with specification, because you build custom combinations of custom cases again and this is what makes code duplication again. So I use them for a single rule and dont nest them.

    Regards

    Jan

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.