Is the Specification Pattern obsolete when you can use Dynamic LINQ?

Asked
Viewd2217

7

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?

  • I’m pretty much facing this exact situation right now, so this question is of great interest to me.

    Michael CookSeptember 21, 2009 19:24

4 个答案

2

动态LINQ使用字符串表达式来允许动态查询构造。因此,实际上我们确实失去了那里的类型安全性。而使用包装器模式(如与其紧密相关的化身的装饰器模式),规范模式,则可以使我们在代码中保持类型安全。我探索使用Decorator Pattern作为查询包装器,以便重用并动态构建查询。您可以在以下位置找到有关代码项目的文章: Linq查询包装器

或者您可以查看我的博客

1

我并不是真的很了解LINQ,但是在我看来,声明式查询系统通常与规范模式有关。特别是,通过在面向对象的环境中将对象组合在一起来实现声明性查询系统。与LINQ相似的IIRC,提供了一层语法糖。

我不知道LINQ是否完全淘汰了这种模式。也许有些情况无法在LINQ中表达?

6

我是C#开发人员,喜欢使用规范模式,因为它离我的业务领域很近。而且,您不会对此模式感到惊讶,如果存在规范类,则它应该起作用。使用Linq,您的基础提供程序可能未实现某些功能,并且直到运行时您才知道。

但是,最终,与linq相比,规格的最大优点是更接近业务,它是一个迷你DSL。对我来说,LINQ是用于集合查询的DSL,而不是用于业务域的DSL。

3

LINQ:

 var oldMans = Persons.Where(x => x.Sex == SexEnum.Masculine && x.Age > 60).ToList();
 

规格:

 var oldMans = Persons.Where(x => IsOldManSpecification(x)).ToList();
 
  • 业务逻辑包含在规范中(使用名称来表明其含义)。
  • DRY :您不会在代码上重复该linq,而只是使用规范

我喜欢使用规范,因为我认为 该规则非常重要,可以在代码中明确显示,并且不自然地属于实体

示例:

 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;
    }
}
 

是从Customer责任中确定他是否能够获得一些信用?银行会问客户是否可以得到贷款?

可能不是。

因此,根据规范,您可以从Customer中删除该逻辑(它永远不属于它)。您可以创建类似于IsAbleToReceiveCreditSpecification的内容,并将所有逻辑放在此处。我们可以更进一步地结合规格,例如:您可以创建SecureAgeSpecificationAssetsGreaterThanSpecification并使用它们来构成IsAbleToReceiveCreditSpecification

因此,我不认为LINQ取代了规范。实际上,它改善了模式。有些规范的实现在内部与IQueriable<T>一起使用LINQ,因此您可以在存储库/ DataAcess级别的ORM查询中使用该规范。