问题
Wikipedia states that the Specification Pattern is where business logic can be recombined by chaining the business logic together using boolean logic. With respect to selecting filtering objects from lists or collections it seems to me that Dynamic LINQ allows me to accomplish the same thing. Am I missing something? Are there other benefits to the Specification Pattern that should be considered as well?
Edit:
I've found some posts that discuss combining LINQ and the Specification Pattern:
Linq Specifications Project
Implementing the Specification Pattern via Linq by Nicloas Blumhardt (Autofac dude)
Has anyone gone done this road and did it become complicated to maintain?
回答1:
Dynamic LINQ uses string expressions to allow the dynamic query construction. So we do in fact lose the type safety there. Whereas using wrapper patterns like the decorator pattern of it closely related incarnation, the specification pattern, allows us to maintain the type safety in code. I explore using the Decorator Pattern as query wrapper in order to reuse and dynamically build queries. You can find the article on code project at: Linq Query Wrappers
Or you can check my blog.
回答2:
I'm a C# developper and like to use the specification pattern, because it is closer of my business domain. Moreover, you don't have any surprise with this pattern, if a specification class exists, it should work. With Linq, your underlying provider maybe hasn't implemented some features, and you won't know it until runtime.
But definitively, the biggest advantage of specification over linq is to be closer to the business, it's a mini DSL. LINQ for me is a DSL for collection query, not for the business domain.
回答3:
LINQ:
var oldMans = Persons.Where(x => x.Sex == SexEnum.Masculine && x.Age > 60).ToList();
Specification:
var oldMans = Persons.Where(x => IsOldManSpecification(x)).ToList();
- The business logic is encapsuled in the specification (with a name that reveal what it is).
- DRY: you don't repeat that linq over the code, you just use the Specification
I like to use specification when I think that the rule is important enough to be explicit in the code and it doesn't belongs naturally to the entity.
Example:
public class Customer
{
//...
public bool IsAbleToReceiveCredit(decimal creditValue)
{
var secureAge = this.Age > 18 && this.Age < 60;
var personalAssetsGreaterThanCreditValue = this.PersonalAssets.Sum(x => x.Value) > creditValue;
return secureAge && personalAssetsGreaterThanCreditValue;
}
}
Is it from the Customer
the responsability to decide if he is able to receive some credit? A bank would ask to the customer if he can receive a loan?
Probably not.
So with specification you can remove that logic from the Customer
(it never belonged to it). You can create something like IsAbleToReceiveCreditSpecification
and put all logic there. We can go further and combine specifications, for example: you could create a SecureAgeSpecification
and a AssetsGreaterThanSpecification
and use them to compose the IsAbleToReceiveCreditSpecification
.
So I don't think LINQ replaces the Specification. In fact it improves the pattern. There are some implementations of Specification that use LINQ internally with IQueriable<T>
, with this you can use the specification inside your ORM queries on the Repository/DataAcess level.
回答4:
I don't know LINQ really, but it seems to me that a declarative query system in general is related to the specification pattern. In particular, implementing a declarative query system by composing objects together in an object-oriented environment. IIRC that's akin to what LINQ does, providing a layer of syntactic sugar.
Whether LINQ completely obsoletes the pattern, I can't tell. Maybe there are corner cases that just can't be expressed in LINQ?
来源:https://stackoverflow.com/questions/1454049/is-the-specification-pattern-obsolete-when-you-can-use-dynamic-linq