面向方面编程与面向对象编程

2023-12-19

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

我已经阅读了很多信息,试图学习这个 AOP 范式的关键,而且我也处于同样的境地,所以,我想更好地了解它在现实世界应用程序开发中的好处。

有人有答案吗?


为什么要“对”呢?这不是“对抗”。您可以将面向方面编程与函数式编程结合使用,也可以与面向对象编程结合使用。它不是“vs”,而是“面向方面编程”with面向对象编程”。

对我来说,AOP 是某种“元编程”。 AOP 所做的一切也可以在没有 AOP 的情况下通过添加更多代码来完成。 AOP 只是让你省去编写这些代码的麻烦。

维基百科有这种元编程的最佳示例之一。假设您有一个带有许多“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.*);

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

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

然而,这个例子也显示了 AOP 的一大缺点。 AOP实际上正在做一些许多程序员认为“反模式 http://en.wikipedia.org/wiki/Anti-pattern”。确切的模式称为“远距离行动 http://en.wikipedia.org/wiki/Action_at_a_distance_(computer_science)".

远距离动作是 反模式(公认的常见 错误)其中某一部分的行为 程序的差异很大 难以或不可能识别 另一部分的运营 程序。

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

Update

只是为了澄清这一点:有些人可能会有我说 AOP 不好的印象,不应该使用。我不是这个意思! AOP 实际上是一个很棒的功能。我只是说“小心使用”。如果您将普通代码和 AOP 混合在一起,AOP 只会导致问题Aspect。在上面的示例中,我们有更新图形对象的值并绘制更新的对象的方面。这实际上是一个方面。将其中一半编码为普通代码,将另一半编码为方面,这会增加问题。

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

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

有人可能会说,如果你可以轻易地滥用 AOP 来造成这么多问题,那么全部使用它并不是一个好主意。然而,哪种技术不能被滥用呢?您可以滥用数据封装,可以滥用继承。几乎所有有用的编程技术都可能被滥用。考虑一种编程语言的局限性,它只包含不能被滥用的功能;一种语言,其中的功能只能按照最初的预期使用。这种语言的局限性如此之大,以至于它是否可以用于现实世界的编程还存在争议。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

面向方面编程与面向对象编程 的相关文章

  • 代理模式和装饰者模式的区别

    你能给出任何好的解释吗 Proxy and 装饰者 我看到的主要区别是 当我们假设Proxy uses 作品 and 装饰者 uses 聚合那么似乎很清楚 通过使用多个 一个或多个 装饰器您可以修改 添加功能到预先存在的实例 装饰 而Pro
  • 如何区分类实现中两个协议的相同方法名称?

    我有两个协议 protocol P1 void printP1 void printCommon end protocol P2 void printP2 void printCommon end 现在 我在一个类中实现这两个协议 inte
  • @Aspect 方面的 Spring 自动装配 bean 为 null

    我有以下弹簧配置
  • 带有 Grails 的 AOP

    我想在我的 Grails 项目中创建自定义日志记录注释 My code class MyService AuditLog def method1 println method1 called method2 AuditLog def met
  • 如何使PHP库松耦合? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 作为属性的类引用

    谷歌对于这类搜索毫无用处 因为你会得到数亿个结果 其中没有一个与特定问题相关 问题很简单 Delphi 中是否可以有类引用属性 如果是这样 怎么办 这是我尝试过的 type TMyObject class end TMyObjectClas
  • PHP - 多个不同的数据库依赖注入类

    我花了过去几个小时试图找到 最佳 最合乎逻辑的方法的答案 以编写一个 php 数据库类以同时连接到一个 postgresql 数据库和一个 mysql 数据库 另外 我想采用依赖注入设计 但对整个概念还是陌生的 到目前为止我已经想出了 cl
  • HK2 MethodInterceptor 与 Jersey 资源

    如何设置aopMethodInterceptor使用泽西岛资源 这是我尝试过的 如下this https hk2 java net 2 2 0 aop example html文档 第 1 步 拦截服务 public class MyInt
  • ASP.NET/ADO.NET:处理 .NET 对象内的许多数据库连接?

    我们有一个 NET 对象 它对数据库进行大量读 写操作 在该对象 或使用它的 ASP 页 的整个生命周期中 它可能会通过查询 更新来访问数据库 1 到 10 次 它不是在每次对象需要访问数据库时打开和关闭数据库连接 而是只是在实例化期间打开
  • Java中的引用变量到底是什么?它与其他变量有何不同?

    我一直在研究 Java 中的继承 作者声明 被引用的对象类型 而不是引用变量的类型 决定了将执行哪个版本的重写方法 这种说法非常令人困惑 这本书所指的是多态性 更具体地通过动态调度 简而言之 想象一下以下类 public class Per
  • 在 Ext JS 构造函数中将项目推入数组会产生多个项目

    我有一个我定义的 Ext JS 类 在这个班级的constructor 我将一个文本字段推送到我的项目数组上 然后添加到我的测试字符串中 数组和字符串在类定义中都声明为空 但是 如果您尝试创建多个类实例 您将看到项目数组在每个实例之间共享
  • 在 init 之外在 java 中创建对象

    因此 对于我正在创建的游戏 我有一些扩展 GameDriver 的类 到目前为止 在所有其他类上我都能够扩展 GameDriver 然后在 GameDriver 中我可以执行以下操作 ArrayList
  • 如何从类外部更改公共 R6 类方法?

    我希望能够在我的 R6 类中重新定义公共方法 以便它根据该类保存的数据类型进行更改 如下所示 library R6 Simple lt R6Class Simple public list dt mtcars my print functi
  • JavaScript - 这个这个

    String prototype foo String prototype foo bar function How can you reference the grandparent string console log this par
  • 在 C++ 中什么时候应该使用“friend”?

    我一直在阅读C FAQ http yosefk com c fqa 并且很好奇friend http yosefk com c fqa friend html宣言 我个人从未使用过它 但我有兴趣探索该语言 使用的一个很好的例子是什么frie
  • 命令式代码与声明式代码[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我试图理解命令式范例和声明式范例之间的区别 因为我必须对 Visual Basic 进行分类 NET 在不同的范式中 除了面向对象之外
  • 我可以在 Laravel 5.2 中创建一个继承自 User 的新类吗?

    我对 Laravel 还很陌生 使用的是迄今为止的最新版本 5 2 因此我遇到了以下困境 我知道 Laravel 附带了一个User开箱即用的类 但我想开发一个系统 在其中我可以有另外两种类型的用户 称为Researcher and Adm
  • Ruby 依赖注入库

    我一直在研究一些 Ruby 依赖注入库 特别是 我检查了Needle http needle rubyforge org and Copland http copland rubyforge org 它们已经存在很长一段时间了 但用途并不多
  • 两个对象相互依赖。那不好吗?

    当我为我的项目构建自己的系统时 我学到了很多关于设计模式的知识 我想问你一个我找不到答案的设计问题 目前我正在使用套接字构建一个带有多个客户端的小型聊天服务器 现在我有三门课 人级其中包含昵称 年龄和房间对象等信息 房间级它保存诸如房间名称
  • 为什么 OOP 中静态类的最佳实践有所不同?

    我目前正在阅读有关 Java 最佳实践的内容 我发现根据这本书 https rads stackoverflow com amzn click com 0321356683我们必须优先选择静态类而不是非静态类 我记得在 C 最佳实践中 我们

随机推荐

  • VBA 系统.集合.队列

    我刚刚发现here http analystcave com excel vba dictionary arrays and other data structures The VBA Queue 内置 Stacks and Queues可
  • Web 视图不适用于某些特定的 url

    public class MainActivity extends AppCompatActivity String url https www pinterest com Override protected void onCreate
  • 如何使用 swift 验证本地玩家?

    我正在尝试将游戏中心集成到我的游戏中并创建排行榜 我已经在 iTunes Connect 上创建了排行榜 启用了游戏中心并创建了一个沙盒测试器 尽管如此 我还是有这个错误 not able to authenticate fail erro
  • 使用 ruby​​ on Rails 安装 Susy 和 Compass

    我刚刚开始使用 ruby on Rails 我尝试做的第一件事就是安装 gems compass 和 susy 在弄清楚我需要将它们包含在 gemfile 中之后 我正在使用 RubyMine 并认为它会为我做这件事 当我尝试将 susy
  • 无损图像压缩工具[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 Running 谷歌页面速度 https developers google com speed 在公
  • 如何在 Web 浏览器视图中从 Ionic 应用程序打开外部链接

    第 1 步 Ionic 创建新应用程序 离子启动 myApp1 侧菜单 第 2 步 创建新页面主页和关于我们 离子生成关于我们的页面 步骤 3 在 关于我们 页面创建按钮 将 URL 重定向到另一个网站 aboutus html GO ab
  • “很抱歉,出了点问题”:rails + nginx + puma + digitalocean + ssl

    我刚刚在生产服务器上的 Rails 应用程序上成功配置了 ssl 但现在 当我尝试访问该站点时 我收到 我们很抱歉 但出了点问题 错误 如果我不使用任何 ssl 设置来禁用 ssl 我的 Rails 应用程序将运行得很好 只有当我使用ssl
  • vim的正则表达式解释

    如果我想要所有带有文本 ruby 但不带有 myruby 的行 那么这就是我要做的 g
  • Rails 中的受保护方法和私有方法

    Ruby 中的方法可见性 公共 受保护和私有方法 已在以下地方得到了很好的解释 这篇博文 http weblog jamisbuck org 2007 2 23 method visibility in ruby 但在 Ruby on Ra
  • python 日志记录关闭和应用程序退出

    我在应用程序中使用日志记录模块 我想到如果日志记录模块支持一种可以优雅地关闭文件句柄等然后关闭应用程序的方法 那就太好了 例如 logger logging getLogger my app logger fatal We re toast
  • Windows 上的 SSH ControlMaster 与 Cygwin 真的可行吗?

    有没有人能够在 Windows 上使用 control master 和 cygwin 创建多个会话而无需重复登录 我需要自动执行一系列 SSH 步骤 但无法要求用户每次都输入所需的标记化密码 我已经配置了我的 cygwin ssh con
  • JDBC 中缺少 dll

    我目前正在 Java 中使用 SQL 最近我收到这个错误 com microsoft sqlserver jdbc AuthenticationJNI
  • mvc 4 windows Azure Request.Url 中的端口号错误

    我正在编写一个小型的 asp net MVC4 Web 应用程序 项目模板是 Visual Studio 2012 中的 azure mvc 4 模板 当我在 razor 视图中请求 Request Url 时 我得到了错误的端口号 例如
  • 从当前日期减去 7 天

    看来我不能从当前日期减去7天 这就是我正在做的 NSCalendar gregorian NSCalendar alloc initWithCalendarIdentifier NSGregorianCalendar NSDateCompo
  • Redux 不会立即更新状态

    我对 Redux 有问题 更可能不是问题而是误解 如果我在函数中进行分派并在存储中写入新值 那么我无法立即从存储中获取该函数的新值 Example testFunc gt console log in func before this pr
  • 如何将地图投影从太平洋中心更改为大西洋中心?

    library sf library tidyverse 我有一个 sf 对象 几何类型 点 预计太平洋上空 bbox xmin 0 ymin 78 xmax 359 ymax 0 WGS 84 我想将 sf 对象重新投影到太平洋中心 0
  • d3.js 堆栈布局从 v3 升级到 v4

    使用 D3 v3 我格式化了数据以匹配 Mike 的示例 以快速启动我的开发过程 示例页面在这里https github com d3 d3 3 x api reference blob master Stack Layout md htt
  • 如何在模型视图转换后获取正在绘制的对象的二维尺寸以在 webgl 上进行命中测试

    我遵循 webgl 基础知识并绘制 2d 对象并使用矩阵来缩放顶点和渲染 在渲染之前我通过width height设置为渲染四边形的顶点 这定义了对象的大小 但在顶点着色器中 我对这些顶点应用变换 如下所示 in vec2 aPositio
  • 当 django 管理员创建用户时,将用户详细信息发送到他的电子邮件

    每当管理员通过 django admin 创建用户详细信息时 我一直尝试将所有用户数据发送到他 她提供的电子邮件 我认为 post save 信号应该用于此过程 但是我的 post save 信号没有在控制台上调用 也不能管理员创建后发送所
  • 面向方面编程与面向对象编程

    与这里和全世界的大多数开发人员一样 我多年来一直使用面向对象编程 OOP 技术开发软件系统 因此 当我读到面向方面编程 AOP 解决了传统 OOP 无法完全或直接解决的许多问题时 我停下来思考 这是真的吗 我已经阅读了很多信息 试图学习这个