使用AOP是否可以更好地解决某些问题?


19

我遇到过面向方面编程的想法,对此我有些担忧。

基本想法似乎是,我们要处理无法使用对象很好地模块化的跨领域关注点,并将其模块化。一切都很好。

但是AOP的实现似乎是从模块外部修改代码的实现。因此,例如,可以编写一个方面来更改当将特定对象作为参数传递给函数中时发生的情况。这似乎直接与模块的想法背道而驰。我应该不能从该模块外部修改模块的行为,否则模块的整个观点都将被推翻。但是方面似乎正是这样做的!

基本上,方面似乎是代码修补的一种形式。对于一些快速的黑客攻击可能很有用;但是,作为一般原则,也许这不是您要执行的操作。在我看来,面向方面的编程似乎是错误的做法,并提出了一般的设计原则。

AOP是一种好习惯吗?使用AOP是否可以更好地解决某些编程问题?


啊,著名的猴子补丁!
Muad'Dib 2010年

1
我已编辑问题以改善其语气,并投票决定重新开放。
罗伯特·哈维

Questio也被重新提出以不同的形式在这里:programmers.stackexchange.com/questions/19344/...
彼得·鲍顿

Answers:


19

面向方面的编程使某些类型的编程成为可能,而无需在整个应用程序或库中不必要地散布与软件的主要功能无关的代码(即横切关注点),就可以进行某些难于完成的编程。示例包括:

  1. 记录与监控
  2. 性能分析
  3. 调试和跟踪
  4. 撤消功能
  5. 验证输入和输出
  6. 改变现有对象的行为
  7. 对象过滤器
  8. 安全实施
  9. 管理交易

通过将此类横切关注点限制在应用程序的单个部分中,然后通过属性,方法调用拦截或动态代理在代码中引用这些功能,可以封装横切行为。封装具有所有好处(即单个修改点),封装将在您的应用程序中提供其他任何地方。

这里的关键点是,AOP封装了以下行为:1)在整个应用程序中通用,以及2)在应用程序主要功能外围的行为。


7

迟到了游戏,但我将其提供给以后可能会偶然发现此问题的开发人员。

如果您的应用程序依赖 AOP 才能正常运行,我强烈建议您不要使用AOP 。方面的工作方式如下:

  • 建议(其他行为)适用于
  • 连接点(可以附加附加代码的地方,例如方法的开始或结束,或触发给定事件的地方)
  • ... 切入点(检测给定连接点是否匹配的模式)的模式匹配

对于长时间从事计算机工作的人来说,使用模式这一事实可能需要仔细观察。因此,这里有一个切入点的示例,该切入点与任何命名方法set都匹配,而与参数无关:

call(* set(..))

因此,这是一个相当广泛的切入点,并且应该清楚地建议您谨慎处理此问题(无双关语),因为您将建议应用于许多事物。

不管怎么说,让我们为所有内容提供建议,无论名称或签名如何!

execution(* *(..))

因此很明显,我们应该谨慎,因为这里有很多功能,但这并不是针对方面的论点-这是要谨慎的论点,因为这里有很多功能,而且模式匹配很容易出错(只要按您喜欢的搜索引擎臭虫,玩得开心)。

所以这看起来是一个相对安全的切入点:

pointcut setter(): target(Point) &&
                   ( call(void setX(int)) ||
                     call(void setY(int)) );

如果找到命名方法setX或对象setY上的方法,则可以明确地提供建议Point。这些方法只能接收int,并且必须为void。看起来很安全,对不对?好吧,如果这些方法存在并且您已应用正确的建议,那将是安全的。如果不是,那就太糟了;它默默地失败了。

举个例子,一个朋友正在尝试调试Java应用程序,每个人在很长一段时间内都会返回错误的数据。这是一次罕见的失败,并且似乎与任何特定事件或特定数据都不相关。这是一个线程错误,非常难以测试或检测。事实证明,他们使用方面来锁定方法并使它们“线程安全”,但是程序员重命名了一种方法,并且切入点未能匹配该方法,从而导致应用程序无提示损坏。

因此,我告诉人们,如果他们必须使用AOP来对待诸如异常之类的方面:在设计良好的系统中,如果没有任何问题,可以将其删除,并且软件仍然可以正常运行。但是,如果程序的功能取决于AOP,则会在程序中引入不必要的脆弱性。

因此,日志记录,调试和跟踪是完美的方面行为示例,但是安全性高吗?不。线程安全?不。

有关AOP的替代方案,请参见traits。它们不是直接固定在语言上,而是直接集成到语言中,不需要“特征感知” IDE(尽管它可以提供帮助),并且如果不存在所需的方法,则编译时会失败。特质在处理关注点分离方面做得更加干净,因为从一开始就更好地定义了问题。我广泛使用它们,它们很棒。


与其争论不应该将AOP用于核心功能,不如说依赖于方法名称的切入点是一个坏主意。我可能会争辩说,锁定和同步也不是AOP的好用例。
Code Bling

2

当您无法访问源代码时,AOP可能是唯一可行的解​​决方案之一。要使用记录横切关注点的陈旧示例:

假设您要在您使用的第三方库中记录控制流。您拥有自己的代码,并已充分记录日志语句。但是,对于该库,您没有源,因此无法添加日志记录语句。由于您确实具有字节码,因此AOP允许您仍然检测该第三方库。

而且,无论如何,如果要创建Logging方面,最好也考虑在自己的代码中使用AOP实现Logging。


记录用于“有趣”的事情。除了“使用这些参数输入”和“退出” AOP日志记录外,您还可以做什么?

@Thorbjorn:记录/调试/跟踪只是AOP可以帮助的许多功能领域之一。我以它为例来说明我的观点。我要说明的是,AOP使您可以更好地控制第三方字节码。
约瑟夫·塔南鲍姆

可以,但是我真的很想知道AOP日志记录是否可以做完输入输出日志记录之外的其他工作?

这取决于您使用的AOP工具,但是您可以做的事情肯定有限制。超越进入-退出日志记录很可能是不可能的。
约瑟夫·塔南鲍姆
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.