【发布时间】:2014-08-05 02:40:56
【问题描述】:
我继承了一个使用以下组件的 clojure 应用程序:
- 码头服务器
- 复合
- 戒指
为了了解应用程序,我想逐步处理请求。 我使用 Emacs 作为我的 IDE。
我可以使用任何工具或技术来完成此任务吗?
【问题讨论】:
标签: emacs clojure functional-programming
我继承了一个使用以下组件的 clojure 应用程序:
为了了解应用程序,我想逐步处理请求。 我使用 Emacs 作为我的 IDE。
我可以使用任何工具或技术来完成此任务吗?
【问题讨论】:
标签: emacs clojure functional-programming
遗憾的是,Clojure 没有任何现成的步进调试器。可以使用 jdb 连接到 jvm 并单步执行字节码,但这不会直接反映您的 Clojure 代码(尤其是由于惰性等因素,可能会导致某些代码在应用程序中从与源代码不同的上下文中进行评估布局会让你期待)。
尽管如此,一切都没有丢失。由于在惯用的 Clojure 代码中非常注重使用不可变数据和纯函数,因此可以直接捕获函数在运行时获得的输入值,以便调查和/或试验新值。例如:
在您的核心命名空间中,您定义您的处理程序并启动码头,并从同一进程启动一个 nrepl 服务器:
(ns my-server.core
(:require [ring.middleware
[json :refer (wrap-json-params)]
[multipart-params :refer (wrap-multipart-params)]]
...
[clojure.tools.nrepl.server :as nrepl-server]))
...
(defn init
[]
(when (= (System/getProperty "with_shell") "true")
(nrepl-server/start-server :port 7888))
(run-jetty handler :port 8080))
在带有服务于特定请求的代码的命名空间中,您可以跟踪传入的数据,以便在 repl 中使用/调查它
(ns my-ns.controllers.home)
(defonce debug (atom []))
(defn home
[request]
(let [in (java.util.Date.)
response (process request)
out (java.util.Date.)]
(swap! debug conj {:in request :out response :fn home :timing [in out]})
response))
然后,从 repl 连接中,您可以通过取消引用原子并查看各种输入和输出值来查询 my-ns.controllers.hom/debug 的状态。这可以概括为调查各种中间值的内容,无论您要跟踪执行的任何位置。由于数据对象通常是不可变的,因此如果您创建一个原子来存储值,则可以有完整的记录来遍历。请注意,通过在计算请求之前和之后创建时间戳,您可以分析请求处理函数主体的执行情况(为了清楚起见,我已将其抽象为单个函数)。
如果您想使用基于打印的跟踪,还有像 clojure.tools.trace 这样的库。
【讨论】: