当您可以使用动态 LINQ 时,规范模式是否已过时?

发布于 2024-08-05 05:53:44 字数 583 浏览 8 评论 0原文

Wikipedia 指出规范模式是可以通过使用布尔值将业务逻辑链接在一起来重新组合业务逻辑的地方逻辑。关于从列表或集合中选择过滤对象,在我看来,动态 LINQ 允许我完成同样的事情。我错过了什么吗?规范模式是否还有其他值得考虑的好处?


编辑:

我发现了一些讨论结合 LINQ 和规范模式的帖子:

Linq 规范项目

通过 Linq 实现规范模式,作者:Nicloas Blumhardt(Autofac 兄弟) )

有没有人走过这条路,维护起来是否变得复杂?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

你另情深 2024-08-12 05:53:44

我是一名 C# 开发人员,喜欢使用规范模式,因为它更接近我的业务领域。此外,您对这种模式不会有任何惊讶,如果存在规范类,它应该可以工作。使用 Linq,您的底层提供程序可能尚未实现某些功能,并且直到运行时您才会知道。

但肯定的是,规范相对于linq的最大优势是更贴近业务,它是一个迷你DSL。 LINQ对我来说是一个用于集合查询的DSL,而不是用于业务领域的。

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.

以酷 2024-08-12 05:53:44

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 中删除该逻辑(它从未属于它)。您可以创建类似 IsAbleToReceiveCreditSpecification 的内容,并将所有逻辑放在那里。我们可以进一步组合规范,例如:您可以创建一个 SecureAgeSpecification 和一个 AssetsGreaterThanSpecification 并使用它们来组成 IsAbleToReceiveCreditSpecification

所以我不认为 LINQ 会取代规范。事实上,它改进了模式。有一些规范的实现在内部使用 LINQ 和 IQueriable,这样您就可以在 Repository/DataAcess 级别的 ORM 查询中使用该规范。

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.

最舍不得你 2024-08-12 05:53:44

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

或者您可以查看我的博客

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.

謌踐踏愛綪 2024-08-12 05:53:44

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

我无法判断 LINQ 是否完全废弃了该模式。也许有些特殊情况无法在 LINQ 中表达?

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?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文