Clojure中面向方面的编程

Chi*_*ron 17 aop jvm clojure

如何在Clojure中实现面向方面编程?我们在Clojure中需要AOP吗?
假设我们想要简单的香草Clojure解决方案(没有AspectJ).

mik*_*era 24

面向方面编程通常用于为代码添加交叉功能,否则这些代码将无可救药地与业务逻辑交织在一起.一个很好的例子是日志记录 - 你真的不希望日志记录代码遍布代码库中的任何地方.

你不需要在Clojure中使用AOP,因为使用Clojure中的其他技术很容易实现这一点.

例如,您可以使用高阶函数来"包装"具有横切功能的其他函数:

; a simple function - the "business logic"
(defn my-calculation [a b]
  (+ a b))

; higher order function that adds logging to any other function
(defn wrap-with-logging [func]
  (fn [& args]
    (let [result (apply func args)]
      (println "Log result: " result)
      result)))

; create a wrapped version of the original function with logging added
(def my-logged-calculation (wrap-with-logging my-calculation))

(my-logged-calculation 7 9)
=> Log result:  16
=> 16
Run Code Online (Sandbox Code Playgroud)

  • 但重新评估并不安全.有关此更灵活的形式化,请参阅Robert Hooke:https://github.com/technomancy/robert-hooke (13认同)
  • @ jcrossley3 - 如果你想要的话,你总是可以用(def my-calculation(wrap-with-logging my-calculation))重新定义原始函数.... (8认同)
  • 作为与AOP的比较,该示例的问题在于,现在开发人员必须调用新的包装器方法而不是原始方法.理想情况下,可以通过调用原始方法来实现日志记录行为.那将更接近AOP提供的,对吧? (6认同)

Joo*_*aat 14

AOP IMHO只是某些静态编程语言的工件.AFAIKS它通常只是一堆非标准的编译器扩展.我还没有看到任何AOP的应用程序无法在更动态的语言中更好地和原生地解决.Clojure当然足够动态,甚至没有考虑宏.

我可能错了,但如果是这样的话,我需要看到一个实际的AOP用例,在纯粹的clojure中也无法实现.

编辑:只是要明确:我拒绝将elisp的建议视为面向方面.在动态语言中,这些只是在需要时使用的技术,除了重新定义函数定义之外不需要语言支持 - 无论如何,所有lisps都支持.

没有必要将它们视为特殊 - 您可以在clojure中轻松定义自己的类似defadvice的函数.例如,参见compojure的包装!宏,实际上已弃用,因为您通常甚至不需要它.

  • 说宏是动态的,因为它们在编译时运行(它们是编译器的钩子),这有点奇怪.更改宏时,需要重新编译调用它的所有代码.在我的书中不是很有活力...... (3认同)
  • 此外,AOP与MOP密切相关,MOP是Common Lisp的metaobject协议(也是Pascal Constanza以提倡CL的AOP而闻名).你认为Common Lisp也是静态的吗?这个答案似乎是(未)教育猜测的随机集合...... (3认同)
  • 我认为这个答案似乎暗示(对于一个不熟悉Clojure的人),Clojure以某种方式无需任何额外的努力就可以消除横切关注点。关于这一点,mikera的答案更为清晰,并包括示例,我认为这应该是公认的答案。该答案及其示例也凸显了一些困难,这一事实只能进一步得出结论,即在Clojure中无法自动解决AOP /交叉问题(以任何其他名称)。 (2认同)

Art*_*ldt 10

面向方面编程是实现Java 中关注点的一种很好的方法.Clojure的可组合抽象实现了这一点.也看到这个问题." 欢乐的Clojure "中的主题非常清楚.

至于面向方面的Clojure的另一个名称的例子,请查看Ring web框架