Answers:
为什么是“ VS”?它不是“ vs”。您可以将面向方面的编程与功能编程结合使用,也可以与面向对象的编程结合使用。它不是“ vs”,而是“使用面向对象编程的面向方面的编程”。
对我来说,AOP是某种“元编程”。如果不添加AOP,只需添加更多代码即可完成所有操作。AOP可以节省您编写这段代码的时间。
Wikipedia拥有此元编程的最佳示例之一。假设您有一个带有许多“ set ...()”方法的图形类。在每种设置方法之后,图形的数据都会更改,因此图形也会更改,因此需要在屏幕上更新图形。假设要重新绘制图形,则必须调用“ Display.update()”。经典方法是通过添加更多代码来解决此问题。在每个set方法的最后,您编写
void set...(...) {
:
:
Display.update();
}
如果您有3种设置方法,那不是问题。如果您有200个(假设的),那么将其添加到任何地方都会变得非常痛苦。同样,无论何时添加新的设置方法,都必须确保不要忘记将其添加到末尾,否则您将创建一个错误。
AOP无需添加大量代码即可解决此问题,而是添加一个方面:
after() : set() {
Display.update();
}
就是这样!您不必告诉自己自己编写更新代码,而只是告诉系统在达到set()切入点之后,它必须运行该代码并将运行此代码。无需更新200种方法,无需确保您不会忘记在新的set-method上添加此代码。另外,您只需要一个切入点:
pointcut set() : execution(* set*(*) ) && this(MyGraphicsClass) && within(com.company.*);
那是什么意思?这意味着,如果一个方法被命名为“集*”(*表示集之后的任何名称可能跟随),无论什么样的方法返回(第一个星号),或者什么参数需要(第三星号)和它MyGraphicsClass的方法与此类是包“ com.company。*”的一部分,则这是set()切入点。我们的第一个代码说“ 运行任何设置切入点的方法后,运行以下代码”。
在这里看到AOP如何优雅地解决问题?实际上,这里描述的所有内容都可以在编译时完成。AOP预处理程序甚至可以在编译类本身之前就可以修改您的源代码(例如,将Display.update()添加到每个set-pointcut方法的末尾)。
但是,此示例还显示了AOP的一大缺点。AOP实际上正在做许多程序员认为是“ 反模式 ”的事情。确切的模式称为“ 远距离动作 ”。
远距离操作是一种反模式(一种公认的常见错误),其中,程序的一个部分的行为基于难以或不可能识别程序的另一部分中的操作而急剧变化。
作为一个项目的新手,我可能只是阅读任何设置方法的代码,并认为它已损坏,因为它似乎不会更新显示内容。我仅通过查看设置方法的代码就看不到,它在执行后将“神奇地”执行一些其他代码来更新显示。我认为这是一个严重的缺点!通过更改方法,可能会引入奇怪的错误。进一步了解某些似乎正常工作但不明显的代码流(如我所说,它们只是神奇地工作……某种程度上),真的很难。
只是为了澄清一下:有些人可能给我留下了印象,我说的是AOP不好,不应该使用。我不是那个意思 AOP实际上是一个很棒的功能。我只是说“小心使用”。仅当您将同一方面的常规代码和AOP混合使用时,AOP才会引起问题。在上面的示例中,我们具有更新图形对象的值并绘制更新后的对象的方面。这实际上是一个方面。将其中一半编码为普通代码,将另一半编码为方面是增加问题的原因。
如果您将AOP用于另一个完全不同的方面(例如,用于日志记录),则不会遇到反模式问题。在这种情况下,该项目的新手可能会想:“所有这些日志消息从何而来?我在代码中看不到任何日志输出”,但这不是一个大问题。他对程序逻辑所做的更改几乎不会破坏日志功能,而对日志功能所作的更改也几乎不会破坏其程序逻辑-这些方面是完全分开的。使用AOP进行日志记录的优点是您的程序代码可以完全专注于做应做的事情,并且仍然可以进行复杂的日志记录,而不会因到处都有数百条日志消息而使代码混乱。同样,当引入新代码时,神奇的日志消息将在正确的时间以正确的内容出现。
因此,在我的示例中,AOP的一种很好用法是始终记录是否已通过set方法更新任何值。这不会产生反模式,也几乎不会引起任何问题。
可能有人会说,如果您可以轻易地滥用AOP来创建许多问题,那么全部使用它是一个坏主意。但是,不能滥用哪种技术?您可以滥用数据封装,也可以滥用继承。几乎每一种有用的编程技术都可能被滥用。考虑一种有限的编程语言,以使其仅包含不可滥用的功能。一种仅在最初使用功能时才可以使用功能的语言。这样的语言将是如此有限,以至于它甚至可以用于现实世界的编程中,都是有争议的。
Display.update
不接受任何参数。如果我们需要传递参数(例如,通常一个log
函数需要一个message
参数)怎么办?然后,我们是否不需要添加大量样板代码来执行AOP方法?
我认为对这个问题没有普遍的答案,但是要注意的一件事是,AOP不能代替 OOP,而是增加了一些分解功能,可以解决所谓的主要成分专制(1)(或横切关注点)。
只要您控制着用于特定项目的工具和语言,它肯定会在某些情况下有所帮助,而且还增加了方面交互方面的新高度复杂性,以及仍需要了解AJDT等其他工具的需求您的程序。
Gregor Kiczales曾经在Google Tech Talks上进行过有关AOP的有趣介绍性演讲,我建议观看:面向方面的编程:模块化的基础研究。
首先,AOP不会替代OOP。AOP扩展了OOP。OOP的思想和实践保持相关性。拥有良好的对象设计可能会使其更容易扩展方面。
我认为AOP带来的想法很重要。我们需要找到一种方法来实现程序中不同类的跨领域关注,而不必自己更改类。但是我认为AOP最终将成为我们使用的其他工具的一部分,而不是单独的工具或技术。我们已经看到了这种情况。
像Ruby和Python这样的几种动态语言具有像mixin这样的语言构造,可以解决相同的问题。这看起来很像AOP,但是更好地集成了该语言。
Spring和Castle以及其他几个依赖注入框架具有将行为添加到他们注入的类的选项。这是进行运行时编织的一种方式,我认为这具有很大的潜力。
我认为您不必学习全新的范例即可使用AOP。这些想法很有趣,但是逐渐被现有工具和语言所吸收。只要保持了解情况并尝试使用这些工具即可。
AOP是处理此概念的新编程范例。一个方面是实现应用程序特定非功能部分的软件实体。
我认为本文是从面向方面的编程开始的好地方:http : //www.jaftalks.com/wp/index.php/introduction-to-aspect-oriented-programming/