AOP与MVC FilterAttributes和拦截器的比较

8
  1. ASP.NET MVC建议使用或扩展内置的授权、操作、结果、异常筛选器。
  2. .Net IoC容器(Unity、Ninject、Autofac)建议使用拦截器。
  3. AOP工具(Postsharp)建议使用它们自己的属性。

现在,我感到很混乱。也许我把它们混合了。 我想构建稳健的代码和稳定的方法,我应该使用什么?

2个回答

6
一切都始于良好的应用程序设计。当您的应用程序设计正确时,您与 UI 框架公开的 AOP 类似功能交互的原因将大大减少(WCF 也是如此)。例如,当您将所有业务逻辑隐藏在通用接口背后,并传递命令消息时(如本文所示),您的控制器将成为薄包装器,往往只执行这样的业务命令。在这种情况下,您可以通过包装这些业务操作来实现授权和异常过滤,使 UI 代码保持干净,没有属性。这些横切关注点可以使用拦截或旧式装饰者来完成。这使您具有更高的灵活性并保持设计 SOLID (具有许多不太明显的长期优势)。
虽然像 PostSharp 这样的代码编织工具很有用,但您应该小心使用它们。它们使用后编译过程将代码注入到您的程序集中。这使得在不触发这些方面的情况下对这些类进行单元测试非常困难。您无法轻松地孤立地测试这些类(这是单元测试的前提条件)。使您的方面依赖于某个静态变量会使方面和单元测试变得更加复杂。静态变量使并行运行单元测试变得困难,并且使用全局常量将要求正确拆除更改的全局设置以防止其他测试受到影响。
虽然代码编织工具通常比拦截产生更好的性能,但与使用装饰者相比,没有性能提升。

编译时注入如何干扰单元测试?你知道,没有编译,你甚至无法进行单元测试。 - John Farrell
@jfar:你的生产代码在编译期间与方面织在一起。因此,你不能再隔离地测试你的生产代码。当单元测试调用某些生产代码时,方面总是会被应用。事实上,你不能进行单元测试,因为按照定义,单元测试在隔离环境中运行。你将拥有的是一个集成测试。现在想要撤回你的“踩”了吗? - Steven
你的代码总是由编译器编织在一起的,生产和单元测试可能会因为编译器而得到不同的版本,任何带有装饰器或 DI 的代码也可能如此。这个答案的缺陷在于 AOP 或 PostSharp 对单元测试没有任何独特或显著的影响。 - John Farrell
1
使用PostSharp,您可以应用一系列属性,每个属性对应一个要应用的行为。使用DI,您可以应用一系列装饰器,每个装饰器对应一个要应用的行为。这里的区别很简单。使用PostSharp属性进行单元测试时,要么全部测试,要么不测试。而使用装饰器模式,您可以单独测试基础类和每个装饰器。 - qujck
@jfar:我可能无法说服你,但既然你对这个主题充满热情,我建议你阅读Matthew D. Groves的AOP in .NET一书,特别是第6章关于单元测试的部分。阅读后,你会明白我在说什么。 - Steven
1
我认为这应该被接受为答案。在某些情况下,使用代码编织确实是可行的,比如实现INPC。对于业务逻辑,如事务、验证、保存更改等,装饰器是正确的选择。使用代码编织进行单元测试是不可行的。 - Ric .Net

4
您引用了三种技术,它们的目的都是在不修改现有代码库的情况下添加功能。ASP.NET MVC和DI限制了您可以在哪些位置使用方面(命名过滤器或拦截器),因为这些技术只能在某些位置添加行为,而不能编辑您的代码。仅基于编译器的技术(例如PostSharp)才能在任何地方添加方面。但是,所有三种都是AOP概念的实现。
在许多情况下,与传统面向对象编程相比,方面证明具有显着优势。并非每个问题都可以通过更好的设计以相同的成本解决传统OOP问题。然而,AOP并不是主流技术,使用非主流技术存在成本和风险(AOP诞生于90年代,而OOP诞生于60年代)。与任何创新一样,不同的参与者对风险和利益的敏感度不同,因此可能成为早期或晚期采用者。
AOP不是单元测试的障碍,但是该主题缺乏共享经验。通常,方面必须作为单独的代码单元进行测试。有必要和非必要的方面。通常,业务代码必须与关键方面一起进行测试,但必须禁用非必要的方面。您可以在构建时静态禁用方面(仅从构建配置中排除某些方面),也可以在运行时禁用它们(使该方面依赖于您在测试期间设置为false的某些静态变量)。

1
你能引用任何一篇更详细解释本质和非本质方面的文章吗? - Steven
1
@Steven 我没有具体的文章想法。在学术文献中,非必要方面的概念实际上被称为“无害建议”。这意味着该方面与其目标(基础代码)完全正交,可以在不影响结果的情况下删除。例如,日志记录和性能监控是无害的,但事务处理或INotifyPropertyChanged则不是。 - Gael Fraiteur
请查看此演示文稿中的第12页 - Zaid Masud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接