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

Architektur erlernen

Golo Roden hat einen netten Blog-Eintrag erstellt, in dem er beschreibt, wie man sich dem Thema Software-Architekturen nähern kann. Meiner Meinung nach hat Golo hier einige Dinge angesprochen, die für den Einstieg ganz nett sind und die Einstiegshürde nehmen. Auch bei mir stellte (und stellt sich immer wieder) die Frage, wie ich zu einem besseren (oder überhaupt einem ;-)) Architekten werden kann. Meiner Meinung nach sind Leute sehr hilfreich, die einfach einen breiten Begriffsschatz zu dem Thema haben. Mit der Zeit schnappt man von diesen Leuten Begriffe auf, die mit dem Thema Architektur zu tun haben und durchsucht dann das Internet für weitere Informationen zu den jeweiligen Themen. Doch der beste Lehrmeister ist immernoch die Praxis. Man muss einfach selbst Erfahrungen sammeln (und das über Jahre hinweg), um feststellen zu können, welche Dinge funktionieren, welche nicht und warum sie das tun bzw. nicht tun. Dieses Hinterfragen ist essentiell und unerlässlich dafür, seine Lösung später auch vor anderen verteidigen zu können.

Zu guter Letzt noch ein Tipp: beim Thema Architektur sollte man 1.) nie auf der eigenen Meinung verharren und vor allem 2.) sein Design der zu erstellenden Anwendung anpassen. Bei 1.) sollte man begründen können, warum eine Architektur schlecht ist und das mit Gründen, die für das aktuelle Projekt auch relevant sind. Jedes Projekt ist anders und besitzt andere Rahmenbedingungen, die Frage nach einer „guten“ Architektur ist daher sehr dynamisch und individuell verschieden! Auch ich bin hier gerade in einem Lernvorgang, umso wichtiger ist es mir diese Erfahrung als Tipp weiterzugeben. Zu 2.) ist zu sagen, dass man das KISS-Prinzip beherzigen sollte: keep it solid and simple! Eine abgefahrene Architektur macht nur dann Sinn, wenn das Projekt sie auch erfordert. Seine Kreativität ausleben zu können ist kein Grund dafür, wilde Architekturspielereien durchzuführen, z.B. durch den Einsatz von Mocking- oder Dependency-Injection-Frameworks. Austauschbarkeit von Komponenten wie dem Datenzugriff ist beispielsweise so eine Spielerei, die nur in wenigen Projekten auch sinnvoll ist. Erst wenn die fachliche Anforderung es konkret erfordert, sollte ein Aspekt in den Entwurf des Architekturdesigns mit einfließen. Man sollte sich immer wieder selber fragen: benötige ich es überhaupt, wenn ja aus welchem Grund und geht es vielleicht auch anders/einfacher? Hilfreich ist auch die Vorstellung, dass man seine Lösung und die einzelnen Teile bei seinem Auftraggeber verteidigen muss. Wenn hier als Argument nur übrigbleibt: „ja das ist jetzt schön austauschbar“, die Anforderungen es aber nicht erfordern, spätestens dann sollte man sich fragen, ob man nicht etwas falsch macht…

Wie gesagt, ich selbst sehe mich perspektivisch als Architekt und finde das ganze Thema sehr spannend, stehe aber 2 Monate nach meinem Studiumsabschluss selber noch ziemlich am Anfang 🙂

Evolution eines Entwicklers

Jeremy Miller hat in seinem Blog einen wirklich interessanten Beitrag zur persönlichen Entwicklung eines Programmierers geschrieben. In diesem Beitrag habe ich mich selbst mehr als einmal wiedergefunden und gesehen, auf welcher Stufe der Evolution ich gerade stehe. Auf jeden Fall empfehlenswert!