规范模式的比较,Func <t,bool>谓词和管道&amp;过滤器</吨,布尔>

时间:2010-08-26 23:51:18

标签: design-patterns architecture extension-methods specification-pattern pipes-filters

我正在做一些R&amp; D工作,因此正在探索设计模式。我最近一直在阅读规范模式,并参考了this伟大的文章。

我对代码的简洁性和清洁度很感兴趣,但我开始比较使用其他技术实现相同的清洁度。

考虑服务层的以下接口合同:

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

所以,一些初步要点:

  • 所有三个都返回Foo对象的集合
  • 这三个人都只拿一个论点
  • 规范方法限制对特定要求的访问
  • 谓词方法基本没有限制
  • 搜索args方法限制对特定要求的访问

现在,进入实施:

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

实施要点:

  • 这三个都非常简单(一行链式代码)
  • 规范和搜索Args已在外部实施过滤。
  • 搜索args方法只是使用IEnumerable扩展方法来检查args

那就是说,在什么条件下你会使用上述3种技术之一?

我对规范模式的看法:

  • 很好,因为它将业务/域要求隔离成可重用的组件
  • 非常容易阅读,使代码说英语
  • 涉及相当多的代码(接口,抽象类)。如果我要使用它,我会将抽象放在一个通用程序集中(所以我的解决方案中没有一堆静态文件)。
  • 仅通过更改规范而非服务层轻松更改要求。
  • 域逻辑的最高可测性(规范)

我对扩展方法(管道和过滤器)的想法:

  • 逻辑中的“重要”,但仍然会产生同样的简单性。
  • 将查询逻辑从服务层隔离到静态方法
  • 仍然需要排序的“反射”(检查提供的搜索参数和建立查询)
  • 允许您首先对架构(存储库,服务层)进行编码,而不考虑特定的业务需求(在某些情况下很方便)。

我对谓词方法的看法:

  • 可用于需要对查询进行粗粒度控制的地方。
  • 适用于规格可能过度的小型项目

我最后的思考逻辑是,如果您正在开发一个复杂的业务应用程序,其中业务需求是预先知道的,但可能会随着时间而变化,那么我会使用规范模式。

但是对于一个“启动”的应用程序,即需求会随着时间的推移而发展,并且有多种方法可以在没有复杂验证的情况下检索数据,我会使用管道和过滤器方法。

你有什么想法?你有没有遇到任何上述方法的问题?有什么建议吗?

即将开始一个新项目,因此这些类型的考虑因素至关重要。

感谢您的帮助。

编辑规范模式的澄清

以下是规范模式的相同用法。

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

2 个答案:

答案 0 :(得分:2)

根据我的小经验:

  1. 用户要求总是改变,我不知道为什么我的老板总是允许改变。所以+1到规范
  2. 这里的程序员更像是“体力劳动者”,而不是“知识工作者”。你知道......整天打字的人。通过使用规范,我可以确保每个人都“打字”。这得到我项目性质的支持。为了相同的目的,它需要许多不同的实现。不要问我为什么。
  3. 使用可提供最高模块性和灵活性的设计模式,当然还有可测试性。这是一个小故事。
    在一个美好的一天,我的伴侣告诉我,他写了一个课程,使我们能够计算出32种计算X的方法。他已经实现了这一切。 Hoho,我认为这是一个如此英雄的编程。他花了几个星期的时间在半夜做这件事。他相信他是一个优秀的程序员,所以他坚持让每个人都使用他的杰作。我们当时并不关心单元测试,所以我们使用了他的杰作。那发生了什么?代码一直崩溃。好吧,从那时起,我意识到单元测试和模块化的重要性。

答案 1 :(得分:0)

好吧,首先我会编写Predicate方法,即使它只用作其他两个的私有实现细节:

private ICollection<Foo> GetFoosBySpecification(Specification<Foo> spec) 
{ 
    return GetFooByPredicate(f => spec.IsSatisfiedBy(f));
} 

搜索参数函数将是一个类似的单行。

除此之外,我真的不能抽象地说什么。我必须更多地了解数据结构,以确定寻找它们的最佳方式。