Аспектно-ориентированное программирование в Clojure

Как добиться аспектно-ориентированного программирования в Clojure? Нужна ли нам AOP в Clojure?
Предположим, что нам нужно решение с гладкой ванилью Clojure (без AspectJ).

Ответы

Ответ 1

AOP IMHO - это просто артефакт некоторых типов статических языков программирования. AFAIKS это обычно просто куча нестандартных расширений компилятора. Я еще не видел приложения АОП, которое невозможно решить лучше и изначально на более динамичных языках. Clojure, конечно, достаточно динамичен, и что даже без учета макросов.

Возможно, я ошибаюсь, но если это так, мне нужно будет увидеть фактический случай использования AOP, который не может быть реализован точно также в чистом clojure.

Изменить: просто чтобы быть ясным: я отказываюсь видеть такие вещи, как совет elisp, как ориентированный на аспекты. В динамических языках это просто методы, которые нужно использовать, когда вам это нужно, без необходимости языковой поддержки, кроме как перепроверять определения функций, которые все ласки поддерживают.

Нет необходимости рассматривать их как специальные - вы можете легко определить свою собственную функцию, основанную на defadvice, в clojure. См. Например, compojure wrap! макрос, который фактически не рекомендуется, так как вам вообще не нужен.

Ответ 2

Аспектно-ориентированное программирование обычно используется для добавления сквозных функций для кода, который в противном случае безнадежно переплетался бы с бизнес-логикой. Отличным примером является ведение журнала - вы действительно не хотите, чтобы код регистрации был разбросан повсюду в вашей базе кода.

Вам не нужен AOP в Clojure, потому что это легко достичь с помощью других методов в 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

Ответ 3

Аспектно-ориентированное программирование - отличный способ добиться разделения забот на Java. Clojure составные абстракции достигают этого очень хорошо. См. этот вопрос. Тема очень хорошо освещена в Радость Clojure.

как для примера Aspect Oriented Clojure другим именем проверьте структуру веб-сайта Ring