2

假设我有一个用 clojure 编写的应用程序,它在运行时生成代码。如何调试该代码 - 我没有源代码?

编辑:我在问这个问题,因为我正在和我的同事谈论 clojure,他说由于上述原因,clojure 程序很难(或不可能)测试。我认为这是一种评估者悲观的方法。如果它是不可测试的,没有人会使用它。

4

4 回答 4

5

Clojure 为您提供了如此强大的功能,因此您不需要debug开发在其他不太强大的语言(如 java、c++ 等)中常见的样式。

  1. 回复_ 您可以随时评估任何函数或表达式。您可以准备环境并重现您需要测试的情况。
  2. 不变性。Clojure 提供了出色的不可变集合和纯函数库。还有 STM 可以让您完全控制应用程序的状态。您可以将程序的可变部分与纯功能代码隔离开来,并使这些部分尽可能小,以便测试负责状态管理的代码变得更加容易(在常见情况下)。测试纯功能部分更加有趣和容易。
  3. 自下而上编程。在 clojure 中,您可以分小块编写代码。您正在使用小型纯函数,直到您可以为下一个继续此过程的底层构建底层(库、dsl)。测试小(纯)功能非常容易。
  4. 记录。显然,您可以在任何代码点记录任何输入参数值。

如果您保持这种编程风格,您将减少真正需要调试的机会。在您的情况下,您可以通过 REPL 完成所有工作。您可以通过 logging 获取生成“调试”动态代码的函数的输入参数。之后,您将以相同的方式获取此动态代码的输入参数。最后,您将同时拥有生成的“调试”代码和输入参数。因此,您可以轻松地重现情况并进行测试。

更新。关于问题的编辑部分,仅仅因为您的程序动态生成代码而说“clojure 程序很难(或不可能)测试”是不正确的。请记住,生成的代码仍然是可以像通常的数据集合一样操作的数据。您无需在断点处构建、运行和冻结整个应用程序即可查看那里发生了什么。我已经描述了测试动态代码的方式。

于 2013-01-14T18:11:22.370 回答
1

您可以尝试使用clojure/tools.trace中的方法使生成的代码包含某种跟踪。

例如,如果您正在定义函数,您可以使用deftrace而不是使用defnwhich 来跟踪调用。

从旧文档(它曾经在 clojure-contrib 中,但从 1.3 开始,它在 clojure/tools.trace 中——这个文档来自 contrib 页面编辑: 链接):

跟踪

用法:(deftrace 名称和定义)

用于代替定义;跟踪此 fn 的每个调用/返回,包括参数。对 deftrace 函数的嵌套调用将打印一个树状结构。

lib 中还有其他方法可能也很方便。

其他调试建议,包括我从哪里获得有关跟踪库的信息。

于 2013-01-14T18:12:54.253 回答
0

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

于 2013-01-14T17:30:49.917 回答
0

像所有其他代码一样 - 将调试语句(如日志)添加到代码中。无论如何,F10-F10-F10 风格的调试器对于任何更复杂的代码都是无用的,不应该使用。

于 2013-01-14T15:55:32.927 回答