简体   繁体   English

如何调试在运行时创建的clojure代码?

[英]How can I debug clojure code which was created at runtime?

Suppose I have an application written in clojure which generates code while it is running. 假设我有一个用clojure编写的应用程序,它在运行时会生成代码。 How can I debug that code - for which I do not have the source code? 我如何调试该代码-我没有源代码?

Edit: I'm asking this question, because I was chatting about clojure with my colleague and he said that clojure programs are hard (or impossible) to test because of the reason stated above. 编辑:我问这个问题,因为我正在和我的同事谈论Clojure,他说由于上述原因,很难测试Clojure程序(或不可能)。 I thought that this is a rater pessimistic approach. 我认为这是评级者的悲观方法。 If it were untestable no one would've used it. 如果无法测试,没有人会使用它。

Clojure gives you so much power so you don't need debug developing style which is common in other less powerful languages like java, c++, etc. Clojure具有强大的功能,因此您不需要debug开发风格,这在其他功能较弱的语言(如Java,C ++等)中很常见。

  1. REPL . REPL You can evaluate any function or expression anytime. 您可以随时评估任何函数或表达式。 You can prepare environment and reproduce the situation you need to test. 您可以准备环境并重现需要测试的情况。
  2. Immutability . 不变性 Clojure provides great immutable collections and pure functions library. Clojure提供了很棒的不可变集合和纯函数库。 Also there is STM that gives you full state control of your application. 还有STM,可为您提供对应用程序的完全状态控制。 You can isolate mutable parts of your program from pure functional code and make those parts as small as possible so testing code responsible for state managing becomes much easier (in common cases). 您可以将程序的可变部分与纯功能代码隔离开来,并使这些部分尽可能小,从而使负责状态管理的测试代码变得更加容易(通常情况下)。 Testing the pure functional part is more fun and easy. 测试纯功能部分更加有趣和容易。
  3. Bottom-up programming . 自下而上的编程 In clojure you can write code by small pieces. 在Clojure中,您可以按小段编写代码。 You're playing with small pure functions until you can build underlying layer (library, dsl) for the next one in which you would continue this process. 您正在使用小的纯函数,直到可以为下一个继续构建该过程的基础层(库,dsl)构建基础为止。 The testing small (pure) functions is very easy job. 测试小型(纯)功能非常容易。
  4. Logging . 正在记录 Obviously you can log any input parameter values at any point of code. 显然,您可以在任何代码点记录任何输入参数值。

If you keep this programming style you will reduce the chance when you really need debugging. 如果您保持这种编程风格,则将减少真正需要调试的机会。 You can do all the job by REPL in your case. 您可以根据自己的情况通过REPL完成所有工作。 You can get input parameters of functions that generate the "debugging" dynamic code by logging . 您可以通过登录获取生成“调试”动态代码的函数的输入参数。 After that you would get input parameters of this dynamic code in the same way. 之后,您将以相同的方式获取此动态代码的输入参数。 You would have both the generated "debugging" code and input parameters at the end. 最后,您将同时具有生成的“调试”代码和输入参数。 So you can easily reproduce situation and test it. 因此,您可以轻松重现情况并进行测试。

Update . 更新 Regarding edited part of the question it's not correct to say that "clojure programs are hard (or impossible) to test" just because your program generates code on the fly. 关于问题的编辑部分,仅仅因为您的程序动态生成代码,就说“ clojure程序很难(或不可能)进行测试”是不正确的。 Keep in mind that generated code is still the data which can be manipulated as usual data collections. 请记住,生成的代码仍然是可以作为常规数据集合进行操作的数据。 You don't need to build, run and freeze the whole application at the breakpoint to see what's going on there. 您无需在断点处构建,运行和冻结整个应用程序即可查看那里发生了什么。 I've already described the way you can test your dynamic code. 我已经描述了测试动态代码的方法。

You could try making the generated code include some sort of trace using the methods from clojure/tools.trace . 您可以尝试使用clojure / tools.trace中的方法使生成的代码包含某种形式的跟踪。

Eg if you're defining functions, you can use deftrace instead of defn which would then trace out calls. 例如,如果您要定义函数,则可以使用deftrace而不是defn来跟踪调用。

From old documentation (it used to be in clojure-contrib, but as of 1.3 it's in clojure/tools.trace -- this doc's from the contrib page EDIT: link ): 从旧的文档(它曾经在clojure-contrib中,但是从1.3开始它在clojure / tools.trace中-该文档来自contrib页面EDIT: link ):

deftrace deftrace

Usage: (deftrace name & definition) 用法:(deftrace名称和定义)

Use in place of defn; 代替defn使用; traces each call/return of this fn, including arguments. 跟踪此fn的每次调用/返回,包括参数。 Nested calls to deftrace'd functions will print a tree-like structure. 嵌套调用deftrace'd函数将打印出树状结构。

There are other methods in the lib that might be handy too. 库中还有其他一些可能也很方便的方法。

Other debugging suggestions, including where I got the info on the trace lib. 其他调试建议,包括在跟踪库中获得信息的位置。

Like all other code - add debug statements (like log) to the code. 像所有其他代码一样-在代码中添加调试语句(例如log)。 F10-F10-F10-style debuggers are useless for any more-less complex code anyway and shouldn't be used. F10-F10-F10样式的调试器对于少得多的复杂代码都是无用的,因此不应使用。

这有点麻烦,但是如果您将生成的代码写到临时文件中,然后加载并评估其内容,那么您将通过堆栈跟踪中的行号获得调试信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM