面向方面编程与对象

像大多数开发人员在这里和全世界一样,我一直在使用面向对象编程(OOP)技术开发软件系统多年。 所以当我读到面向方面编程(AOP)时,解决了许多传统OOP并未完全或直接解决的问题,我停下来思考一下,它是真的吗?

我已经阅读了大量的信息,试图学习这种AOP范例的关键,并且我在同一个地方,所以我想更好地理解它在现实世界应用程序开发中的好处。

有人有答案吗?


为什么“vs”? 这不是“vs”。 您可以将面向方面编程与功能编程结合使用,也可以与面向对象相结合。 这不是“VS”,它是“面向对象编程面向方面编程”。

对我而言,AOP是一种“元编程”。 只需添加更多的代码,AOP所做的一切都可以在没有它的情况下完成。 AOP只是节省你编写这段代码。

维基百科有这个元编程的最好例子之一。 假设你有一个包含许多“set ...()”方法的图形类。 在每种设置方法之后,图形的数据发生改变,因此图形改变并且因此图形需要在屏幕上更新。 假设重新绘制图形,您必须调用“Display.update()”。 传统的方法是通过添加更多的代码来解决这个问题。 在你写的每一套方法的末尾

void set...(...) {
    :
    :
    Display.update();
}

如果你有3个设置方法,那不是问题。 如果你有200个(假设的),那么到处添加这个就变得非常痛苦。 同样,无论何时添加新的set-method,您都必须确保不要忘记将其添加到最后,否则您只是创建了一个bug。

AOP在不添加大量代码的情况下解决了这个问题,而是增加了一个方面:

after() : set() {
   Display.update();
}

就是这样! 您不要自己编写更新代码,而只需告诉系统在达到set()切入点后,它必须运行此代码并运行此代码。 无需更新200个方法,无需确保您不会忘记在新的set-method中添加此代码。 另外你只需要一个切入点:

pointcut set() : execution(* set*(*) ) && this(MyGraphicsClass) && within(com.company.*);

那是什么意思? 这意味着如果一个方法被命名为“set *”(*表示设置后可能有任何名字),无论该方法返回的是什么(第一个星号)或它需要什么参数(第三个星号),并且它是MyGraphicsClass的一个方法,并且这个类是包“com.company。*”的一部分,那么这是一个set()切入点。 我们的第一个代码表示“在运行任何设置切入点的方法之后,运行以下代码”。

看看AOP如何在这里优雅地解决问题? 实际上这里所描述的一切都可以在编译时完成。 AOP预处理器可以在编译类本身之前修改源代码(例如,将Display.update()添加到每个set-pointcut方法的末尾)。

但是,这个例子也显示了AOP的一个大缺点。 AOP实际上正在做许多程序员认为的“ 反模式 ”。 确切的模式被称为“在远处行动”。

远距离行动是一种反模式(一种公认的常见错误),其中一个程序的某一部分的行为根据难以或无法识别该程序的另一部分中的操作而变化很大。

作为项目的新手,我可能只是读取任何set-method的代码,并认为它已损坏,因为它似乎没有更新显示。 我看不到通过查看set-method的代码,在执行它之后,其他代码将“神奇地”执行以更新显示。 我认为这是一个严重的缺点! 通过修改方法,可能会引入奇怪的错误。 进一步理解代码在某些事情似乎正常工作的代码流程中,但并不明显(正如我所说的,他们只是神奇地工作......不知何故),真的很难。

更新

只是为了澄清:有些人可能会有印象,我说AOP是坏东西,不应该使用。 这不是我说的! AOP实际上是一个很棒的功能。 我只是说“小心使用它”。 如果您将相同方面的普通代码和AOP混合使用,AOP只会导致问题。 在上面的例子中,我们具有更新图形对象值并绘制更新对象的方面。 这实际上是一个方面。 将它的一半编码为正常的代码,另一半作为方面是什么增加了这个问题。

如果您将AOP用于完全不同的方面,例如用于日志记录,则不会遇到反模式问题。 在这种情况下,项目的新手可能会想知道“所有这些日志消息来自哪里?我在代码中看不到任何日志输出”,但这不是一个大问题。 他对程序逻辑的改变几乎不会破坏日志设施,对日志设施所做的更改几乎不会破坏他的程序逻辑 - 这些方面是完全分开的。 使用AOP进行日志记录有一个优点,即您的程序代码可以完全专注于做它应该做的任何事情,并且您仍然可以进行复杂的日志记录,而不必让任何地方的数百条日志消息混淆您的代码。 此外,当新代码被引入时,神奇的日志消息将在正确的时间显示正确的内容。 新手程序员可能不明白他们为什么会在那里或他们来自哪里,但由于他们会在“正确的时间”记录“正确的事情”,他只能高兴地接受他们在那里并继续前进的事实。

因此,在我的示例中,AOP的一个很好的用法是,如果通过set方法更新了任何值,则总是记录日志。 这不会产生反模式,也不会成为任何问题的原因。

有人可能会说,如果你可以轻易地滥用AOP来创建这么多问题,那么全部使用它是一个坏主意。 但是哪种技术不能被滥用? 你可以滥用数据封装,你可以滥用继承。 几乎所有有用的编程技术都可能被滥用。 考虑一种如此有限的编程语言,它只包含不能被滥用的功能; 一种功能只能用于最初打算使用的语言。 这种语言如此有限,以至于它甚至可以用于真实世界的程序设计是有争议的。


OOP和AOP不是相互排斥的。 AOP可以成为面向对象的良好补充。 AOP特别方便用于将标准代码(如日志记录,性能跟踪等)添加到方法中,而不用此标准代码堵塞方法代码。


面向方面的pogramming提供了一个很好的方式来实现横切关注,如日志记录,安全性。 这些横切的外观是一些逻辑,必须在许多地方应用,但实际上与业务逻辑没有任何关系。

您不应该将AOP看作是OOP的替代品,更像是一个不错的附加组件,它使您的代码更加干净,松散耦合并专注于业务逻辑。 所以通过应用AOP,您将获得两项主要优势:

  • 每个问题的逻辑现在都集中在一个地方,而不是遍布整个代码库。

  • 类更清洁,因为它们只包含主要关注(或核心功能)的代码,而次要关注已转移到方面。

  • 链接地址: http://www.djcxy.com/p/22921.html

    上一篇: Aspect Oriented Programming vs. Object

    下一篇: Why functional languages?