构建和部署 Clojure 应用程序的最佳实践:好的教程? [英] Best practices in building and deploying Clojure applications: good tutorials?

查看:14
本文介绍了构建和部署 Clojure 应用程序的最佳实践:好的教程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 Clojure 的新手,并开始尝试构建应用程序.

I am new to Clojure, and am beginning to experiment with building an application.

到目前为止,我所看到的关于编译 Clojure 程序的教程都涉及交互性.例如,加载 REPL 并键入(加载文件this-or-that")以运行.这很好,但还不够.

So far, everything I've seen about tutorials on compiling Clojure programs involves interactivity. For example, "load up the REPL and type (load-file "this-or-that") to run. This is fine, but it's not enough.

我已经习惯了像 C 或 Delphi 这样的语言的编辑-编译-运行习语,我本能地被驱使进行编辑,然后点击M-x 编译".

I am so used to the edit-compile-run idioms of languages like C or Delp that I am instinctively driven to make edits, then hit "M-x compile".

问题是,我理解的lein uberjar"相当于make",即使对于hello world来说执行起来也非常缓慢.所以我将不得不弄清楚这个交互式开发"的东西是如何工作的,停止使用 uberjar 就像它是快速制作一样,并且只在一天结束时保存它.

The problem is that "lein uberjar", which I understand is the equivalent to "make", is painfully slow to execute even for a hello world. So I'm going to have to figure out how this "interactive development" stuff works, stop using the uberjar like it's quick make, and save it only for the end of the day.

我在构建(使用 lein uberjar)时注意到的另一件事是我正在开发的小型 GUI 应用程序在编译过程中弹出框架,就好像它们在编译时执行.这对我来说似乎有点违反直觉;它并不像我想象的那样类似于制造".

Another thing I noticed while building (using lein uberjar) is that the small GUI app I am working on pops up frames in the compilation process, as if they are executing while compiling. It just seems a bit counterintuitive to me; it is not quite as analogous to "make" as I had thought.

我知道 Lisp 的开发方式是在 REPL 中以交互方式工作,我并不想改变这一点:我想适应这种生活方式.不幸的是,我很少看到有关如何执行此操作的文档形式.例如,如何重置机器的当前状态.只是不停地编译各个片段而无法进行某种重置,这似乎有点混乱.

I know the Lisp way of developing things is interactively working in the REPL, and I am not trying to change that: I would like to adapt to this way of life. Unfortunately, I have seen little in the form of documentation on how to do so. For instance, how to reset the current state of the machine. It just seems kind of messy to just keep compiling individual snippets on the fly without being able to do some sort of reset.

我在 Clojure(和 Lisp)上看到的大多数教程一般都侧重于 REPL 中的黑客攻击.应用程序部署的最佳实践对我来说仍然是个谜.我的用户只是用户;他们不会是将文件加载到 REPL 中的开发人员.

Most tutorials I have seen on Clojure (and Lisp) in general seem to focus on hacking in the REPL. Best practices on the deployment of applications remains a mystery to me. My users are just going to be users; they are not going to be developers that are going to load files into a REPL.

所以这是我的问题:有关构建 Clojure 应用程序(包括部署)的整个过程的良好信息或教程的任何资源?

So here is my question: any resources for good information or tutorials on the entire process of building a Clojure application, including deployment?

(注意:我已经安装并运行了所有先决条件(例如 Emacs、Slime、Leiningen 等),所以这不是一个问题).

(Note: I have all of the prerequisites installed and working (e.g. Emacs, Slime, Leiningen, etc.), so this is not a question about that).

推荐答案

几个快速提示,然后是一些链接:

A couple of quick hints, then some links:

在开发过程中不要使用lein uberjar;更喜欢 lein jar.不同之处在于 lein uberjar 将您所有的依赖项放在生成的 jar 中(包括 Clojure 本身),因此您的单个 jar 是一个完全自包含的包,其中包含您的应用程序;lein jar 只 jar 自己的代码.uberjar 方法对部署有明显的好处,但对于开发来说,你应该能够在运行你的应用程序时使用适当的类路径,从而节省准备 uberjar 所需的时间.如果您不想手动管理测试运行的类路径,请查看 lein run 插件.

Don't use lein uberjar during development; prefer lein jar. The difference is that lein uberjar puts all your dependencies in the generated jar (including Clojure itself), so that your single jar is an entirely self contained package with your app inside; lein jar only jars your own code. The uberjar approach has obvious benefits for deployment, but for development, you should be able to just use the appropriate classpath when running your app, saving yourself the time necessary to prepare an uberjar. If you don't want to hand-manage the classpath for test runs, check out the lein run plugin.

此外,很可能您的大部分代码实际上不应该被 AOT 编译.在某些 Java 互操作场景中,AOT 是必需的,但在大多数情况下,它会带来启动速度的轻微提升以及与 Clojure 不同版本的二进制兼容性的烦人问题.我想后一个问题与 uberjar-ed 独立应用程序类型的项目无关,但如果可能的话,至少任何库代码都应该被 JIT-ed.使用Leiningen,您可以在project.clj 中的defproject 表单中放置一个:namespaces 子句来确定要编译哪些名称空间;默认情况下,您遗漏的任何内容当前都将进行 JIT.旧版本的 Leiningen 过去默认编译所有内容,这实际上是升级的好理由!

Also, most likely the majority of your code should not actually be AOT compiled. AOT is necessary in some Java interop scenarios, but most of the time it brings one a slight boost in startup speed and annoying problems with binary compatibility with different releases of Clojure. I suppose the latter issue is not relevant to an uberjar-ed standalone app kind of project, but any library code at least should be left to be JIT-ed if at all possible. With Leiningen, you can put a :namespaces clause in the defproject form in project.clj to determine which namespaces are to be compiled; whatever you leave out will currently be JIT-ed by default. Older versions of Leiningen used to compile everything by default, which is actually a good reason to upgrade!

至于在编译期间弹出的窗口,我猜您要么在宏扩展期间运行弹出窗口的代码,要么在任何函数定义或类似构造之外运行.(类似于顶层的 (println "Foo!") .)我想这是你不应该做的事情——除非你打算将代码作为脚本运行,无论如何.为避免该问题,请将副作用代码包装在函数定义中,并使用 project.clj 中的 :main 子句为您的应用程序提供入口点.(如果你说 :main foo,那么 foo 命名空间中的 -main 函数将被用作你的应用程序的入口点.那就是无论如何,默认值,至少上面提到的 lein run 似乎有硬编码的名称 - 不确定 lein 本身.)

As for the windows popping out during compilation, I would guess that you're either running window-out-popping code during macro expansion time or outside of any function definition or similar construct. (Something like a (println "Foo!") at the top level.) That's just something you shouldn't do, I suppose -- unless you are planning to run your code as a script, anyway. To avoid the problem, wrap side-effecting code up in function definitions and provide an entry point to your application using the :main clause in project.clj. (If you say :main foo, then the -main function from the foo namespace will be used as the entry point to your app. That's the default, anyway, and at least the above mentioned lein run seems to have the name hardcoded -- not sure about lein itself.)

至于重置 REPL 的状态——您可以重新启动它.使用 SLIME,M-x slime-restart-inferior-lisp 将做到这一点,同时保持 Emacs 会话的所有其他状态.

As for resetting the state of the REPL -- you can just restart it. With SLIME, M-x slime-restart-inferior-lisp will do just that while maintaining all other state of your Emacs session.

另请参阅 Clojure Google 群组中的这些讨论:

See also these discussions on the Clojure Google group:

  1. Clojure 系统管理
  2. 准备用于打包的 clojure(原为:Re: 用于系统管理的 Clojure)
  3. Leiningen、Clojure 和图书馆:我错过了什么?

这篇关于构建和部署 Clojure 应用程序的最佳实践:好的教程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆