design-patternsarchitectureextension-methodsspecification-patternpipes-filters

Comparison of Specification Pattern, Func<T,bool> Predicates and Pipes & Filters


I'm doing some R&D work, and as such am exploring design patterns. I have recently been reading up on the Specification pattern and was referred to this great article.

I was intrigued by the simplicity and cleanliness of the code, but i started to draw some comparisons to implementing the same cleanliness using other techniques.

Consider the following interface contract for a service layer:

public interface IFooDataService
{
   ICollection<Foo> GetFoosBySpecification(Specification<Foo> specification);
   ICollection<Foo> GetFooByPredicate(Func<Foo,bool> predicate);
   ICollection<Foo> GetFooBySearchArgs(FooSearchArgs searchArgs);
}

So, some initial points:

Now, onto the implementation:

public ICollection<Foo> GetFoosBySpecification(Specification<Foo> specification)
{
    return fooDataRepository
            .Find()
            .Where(f => specification.IsSatisfiedBy(f))
            .ToList();
}

public ICollection<Foo> GetFooByPredicate(Func<Foo, bool> predicate)
{
    return fooDataRepository
            .Find()
            .Where(predicate)
            .ToList();
}

public ICollection<Foo> GetFooBySearchArgs(FooSearchArgs searchArgs)
{
    return fooDataRepository
            .Find()
            .WhereMeetsSearchCriteria(searchArgs)
            .ToList();
}

Points on the implementation:

So, that being said, under what conditions would you use one of above 3 techniques?

My thoughts on Specification Pattern:

My thoughts on Extension Methods (Pipes & Filters):

My thoughts on Predicate Method:

My final thought logic is that if you are working on a complex business application where business requirements are known up front but may change over time, then i would use Specification pattern.

But for a application that is a "startup", ie requirements will evolve over time and has a multitude of ways to retrieve data without complex validation, i would use the Pipes and Filters methods.

What are your thoughts? Have any of you run into problems with any of the above methods? Any recommendations?

About to start a new project so these types of considerations are critical.

Thanks for the help.

EDIT for Clarification on Specification pattern

Here is same usage of the Specification pattern.

Specification<Foo> someSpec; // Specification is an abstract class, implementing ISpecification<TEntity> members (And, Or, Not, IsSatisfiedBy).
someSpec = new AllFoosMustHaveABarSpecification(); // Simple class which inherits from Specification<Foo> class, overriding abstract method "IsSatisfiedBy" - which provides the actual business logic.    
ICollection<Foo> foos = fooDataService.GetFoosBySpecification(someSpec);

Solution

  • From my little experience :

    1. User requirement always change and i don't know why my boss always allows that changes to come. So +1 to Specification
    2. Programmer here is more like "manual worker" than "knowledge worker". You know.. the one who types all day long. By using Specification, i can ensure myself that everybody "types". This is supported by the nature of my project. It needs many many different implementation for same purpose. Don't ask me why.
    3. Use a design pattern which gives you highest modularity and flexibility and of course testability. Here's a little story.
      In a one fine day, my mate told me that he wrote a class which enabled us to calculate 32 kinds of way of calculating X. And he already implemented all that. Hoho, that was such a heroic programming i think. He spent several weeks doing that in the middle of the night. He believed that he was a good programmer so he insisted everybody to use his masterpiece.
      We, at that time, didn't care about unit testing so we used his masterpiece. What happened then? The code crashed all the time. Well, from that time i realized how important unit test and modularity are.