Query Objects and the Specification Pattern
posted on 10/07/08 at 10:55:44 pm by Joel Ross
The other night, I had an eye opening moment when I finally understood how I could use query objects to allow me to use a generic repository, yet still be able to have re-usable queries. But one thing I didn't quite get was how this related to the Specification pattern. The samples I found (including the one I linked to) all used the term Specification, but that wasn't how I understood the specification pattern to work.
But just by adding one method to the base class, it (again) became clear how the two are related:
1: public bool IsSatisfiedBy(T candidate)
2: {
3: return SatisfyingElementsFrom(new[] { candidate }.AsQueryable()).Any();
4: }
By adding this, you can now pass an entity to it, and determine if that entity satisfies the specification. As a result, I've renamed my base class to SpecificationBase<T>, and can now use them for validation purposes as well.
Now, the next question. Does this violate the Single Responsibility Principle? At first glance, I thought it did, because it's used to do two different things: query and validate. But taking a closer look, I don't think it does. How it's used externally is different than what it does internally - which is check that a collection of entities (even if the collection is only one element) satisfies a given specification. More to the point, it's single reason for change would be if there was a change to how it determines that an entity meets the specification. That isn't related to querying or validating at all - that's above this layer.
Of course, I could be wrong. In your opinion, does this violate SRP? If so, how would you fix it?
Tags: NHibernate | Specification Pattern | SRP
Categories: Development, C#