我理解面向对象的编程,并且已经编写了OO程序很长一段时间.人们似乎在谈论面向方面的编程,但我从未真正了解它是什么或如何使用它.什么是基本范式?
这个问题是相关的,但并没有提出这个问题:
我主要是一名Java开发人员.我遇到了很多喜欢AOP的Java开发者.我也看到越来越多的AOP"设计模式"最近出现,似乎被广泛采用.即便如此,由于几个原因,我仍然不相信OO代码中的AOP通常是个好主意.
它以不透明的复杂性形式为代码添加了"魔力",这可能非常难以调试,并且可能使调试它所影响的面向对象的代码变得非常困难.
在我看来,大多数情况下是不必要的,而且(更糟糕的是)经常习惯于避免设计好,或者补偿以前糟糕的设计.
这是我在过去几年中经常看到的一个例子,作为我的问题的背景.
在AOP之前(来自Hibernate文档)
public void saveMyEntityToTheDatabase(MyEntity entity) {
EntityTransaction tx = null;
try {
tx = entityManager.getTransaction();
tx.begin();
entityManager.persist(entity);
tx.commit();
} catch (RuntimeException e) {
if(tx != null && tx.isActive()) {
tx.rollback();
}
throw e;
}
}
Run Code Online (Sandbox Code Playgroud)
AOP之后
@Transactional
public void saveMyEntityToTheDatabase(MyEntity entity) {
entityManager.persist(entity);
}
Run Code Online (Sandbox Code Playgroud)
对许多人而言,AOP似乎是一个明显的胜利.对我来说,原始问题是API抽象级别不一致的症状.也就是说,它EntityManager比使用它的消息的业务级API低很多.这个问题可以通过更合适的抽象级别和更好的(OO)设计来解决.
OO解决方案
public void saveMyEntityToTheDatabase(MyEntity entity) {
database.performInTransaction(new Save(entity));
}
Run Code Online (Sandbox Code Playgroud)
此解决方案假定database对象包含与负责管理@Transactional方法的方面相同类型的事务逻辑.这解决了我上面关注的问题,因为它更明显地表明存在管理与之交互的东西EntityManager,而不是引入另一种编程范例.
最后,我的问题是:AOP可以做什么OOP不能?我有点确信它在跟踪日志记录中的用处,也许是默认toString()实现或类似的东西,但我很想知道是否有人发现它比OO明显优于特定类型的问题.
我想在我的所有公共方法中添加"trace"消息,如下所示:
public void foo(s:String, n:int) { // log is a log4j logger or any other library
log.trace(String.format("Enter foo with s: %s, n: %d", s, n))
...
log.trace("Exit foo")
}
现在我想log.trace用AOP(和字节码检测)自动将所有这些添加到我的方法中.我在考虑AspectJ.是否有意义?你知道任何开放源代码吗?
面向方面的编程是我很难找到任何好的信息的主题.我的旧软件工程教科书只是简单地(和模糊地)提到它,维基百科和我能够在其上找到的各种其他教程/文章给出了超学术,高度抽象的定义,它是什么,如何使用它,何时使用它.定义我似乎并不理解.
我(非常差)对AOP的理解是,生成高质量软件系统的许多方面都不能很好地融入一个漂亮的小内聚包中.一些类,如Loggers,Validators,DatabaseQueries等,将在您的代码库中使用,因此将是高度耦合的.我对AOP的理解(再次,非常差)是它关注如何处理这些类型的"通用耦合"包的最佳实践.
问题:这是真的,还是我完全没有?如果我完全错了,有人可以给出简明扼要的解释,说明AOP是什么,所谓的方面的例子,甚至可能提供一个简单的代码示例?
我浏览了在线文档,阅读了wiki条目,帖子和博客,但我仍然感到困惑.
我一直是一个OO男人,我想知道我是否需要犯叛国罪.
说真的,我很快就要开始一个新项目,我想在开始时做出正确的选择.
我最近开始尝试使用Python装饰器(以及高阶函数),因为看起来它们可能会使我的Django单元测试更加简洁.例如,而不是写:
def visit1():
login()
do_stuff()
logout()
Run Code Online (Sandbox Code Playgroud)
我可以改为做
@handle_login
def visit1():
do_stuff()
Run Code Online (Sandbox Code Playgroud)
然而,经过一些实验,我发现装饰器并不像我希望的那么简单.首先,我在不同的例子中找到了不同的装饰器语法,直到我了解到装饰器在接受参数时表现得非常不同.然后我尝试装饰一个方法,并最终知道它不起作用,因为我首先必须通过添加方法将我的装饰器变成描述符__get__.在整个过程中,我最终混淆了几次,但仍然发现调试这个"装饰"代码比通常用于Python更复杂.我现在正在重新评估我的代码中是否真的需要装饰器,因为我最初的动机是节省一些打字,而不是因为有任何真正需要高阶函数的东西.
所以我的问题是:装饰者应该被大量使用还是少量使用?避免使用它们是否更加Pythonic?
如何在C#中使用AOP将属性应用于类函数?
更新:我有点不清楚在什么情况下应该使用AOP?由于我们可以使用AOP进行日志记录,安全性(身份验证),请建议我们可以从AOP中获益的其他方案
AOP是否可以用于在应用程序进程中的不同运行线程之间共享数据?