views:

247

answers:

2

Like any design pattern the Specification Pattern is a great concept but susceptible to overuse by an eager architect/developer.

I am about to commence development on a new application (.NET & C#) and really like the concept of the Specification Pattern and am keen to make full use of it. However before I go in all guns blazing I would be really interested in knowing if anyone could share the pain points that experienced when use the Specification Pattern in developing an application.

Ideally I'm looking to see if others have had issues in

  • Writing unit tests against the specification pattern
  • Deciding which layer the specifications should live in (Repository, Service, Domain, etc)
  • Using it everywhere when a simple if statement would have done the job
  • etc?

Thanks in advance

+3  A: 

As David pointed out in his comment, a lot of what is useful about specification can now be more succinctly achieved with the likes of LINQ.

Instead of a new specification type, you can create arbitrary specifications on-the-fly: GetCustomers().Where(customer => customer.IsActive && customer.City == "Oakland");

This is not a complete replacement for specification, however, for a couple of reasons:

  1. The sorting/filtering happens in the consuming class after returning all customers. If you are dealing with anything other than in-memory objects, this is sub-optimal (LINQ-to-SQL and the like are exceptions because they compile and optimize queries and execute them on the server/remote side, returning only the desired results).
  2. Your API is wide-open to any query if you expose collections and leave the specification to LINQ queries. If you want to constrain what or how much can be retrieved, you'll need a set of specifications with which to query.

There is certainly no need to use it everywhere, and it is very possible that you won't need it at all; I don't know your domain or what you're working on.

I think the best advice is not to look to use it. You'll see when it is warranted, most likely when you start writing a class that looks like the first example in the article to which you linked.

Just keep it in your mental pattern repository so you've got if you need it; if you never use it, it only means that you didn't need it, and that is fine.

The choice of layer is subject to the nature of the specifications and usage. In many cases they are helpers in support of a service layer, but in some cases they encapsulate domain logic.

As for unit testing, remember that your specifications are units or contain units. Don't test a method that accepts a specification with all possible combinations of specification; test the specifications themselves to make sure that they behave as expected, and then you can reuse the same specifications with confidence in many methods and classes.

Hope that's a bit helpful.

Jay
@Jay thanks so much for your insightful response. Cheers Kane
Kane
No problem. I should also mention that using lambdas allows an additional form of specification than the "client-side" LINQ: passing anonymous delegates as method arguments. `GetCustomers(customer => customer.IsActive `
Jay