构建和部署Clojure应用程序的最佳做法:好的教程? [英] Best practices in building and deploying Clojure applications: good tutorials?
问题描述
到目前为止,我已经看到关于编译Clojure程序的教程的一切都涉及交互性。例如,加载REPL并输入(加载文件这个或那个)来运行,这很好,但还不够。
I我习惯于C或Delphi这样的编辑编译运行语言,我本能地驱动编辑,然后点击Mx编译。
问题是,我所理解的lein uberjar相当于make,即使是一个你好世界也是很难执行的,所以我要弄清楚这个交互式开发的东西如何工作,停止使用uberjar喜欢它的快速制作,并保存它只在一天结束。
另一件事我注意到在建立(使用lein uberjar)是小GUI应用程序我正在编译过程中弹出框架,就好像它们在编译时执行一样,似乎对我来说有点违反直觉,它不像我所说的那样类似于make思想。
我知道Lisp开发的方式是交互式的在REPL工作,我不想改变:我想适应这种生活方式。不幸的是,我没有看到关于如何这样做的文件的形式。例如,如何重置机器的当前状态。看起来好像有点乱七八糟,只是继续编写个别代码片段,而无需进行某种重置。
我在Clojure(和Lisp)中看到的大多数教程)一般似乎集中在REPL中的黑客攻击。部署应用程序的最佳做法对我来说仍然是一个谜。我的用户只是用户;他们不会是要将文件加载到REPL中的开发人员。
所以这里是我的问题:任何资源,以获得良好信息或教程的整个过程构建Clojure应用程序,包括部署?
(注意:我已经安装和工作的所有先决条件(例如Emacs,Slime,Leiningen等),所以这不是一个问题) / p>
几个快速提示,然后一些链接:
Don在开发过程中不要使用 lein uberjar
喜欢 lein jar
。不同的是, lein uberjar
将所有依赖项放在生成的 jar
(包括Clojure本身)中,以便您的单个jar是一个完全独立的包,你的应用程序在里面; lein jar
只有你自己的代码。 uberjar
方法对于部署有明显的好处,但是对于开发,您应该能够在运行应用程序时使用适当的类路径,节省您准备一个uberjar所需的时间。如果您不想手动管理测试运行的类路径,请查看 lein运行
插件。
此外,您的代码中绝大多数的代码实际上不应该被编译为AOT。在某些Java互操作场景中,AOT是必需的,但大多数情况下,它可以轻松提升启动速度,并且与不同版本的Clojure的二进制兼容性造成烦人的问题。我认为后一个问题与一个 uberjar
独立应用程序类型的项目无关,但是任何图书馆代码至少应该是JIT-ed,如果可能的话。使用Leiningen,您可以在 project.clj中的
来确定要编译的命名空间;默认情况下,您所遗漏的任何内容当前都将被JIT-ed。旧版本的Leiningen用于默认编译所有内容,这实际上是升级的一个很好的理由。 defproject
表单中放入:namespaces
至于在编译过程中弹出的窗口,我猜想你'在宏扩展时间期间或在任何函数定义或类似结构之外运行窗口弹出代码。 (顶级的东西就像一个(printlnFoo!)
)这只是你不应该做的,我想 - 除非你打算运行代码作为脚本,反正。为避免此问题,请在功能定义中包含副作用代码,并使用 project.clj中的
。 (如果你说:main
子句为应用程序提供入口点:main foo
,那么 -main
函数从 foo
命名空间将被用作您的应用程序的入口点,这是默认值,无论如何,至少上述 lein运行
似乎具有硬编码的名称 - 不知道lein本身。)
至于重置REPL的状态 - 你可以重新启动它。使用SLIME,Mx slime-restart-inferior-lisp将保持Emacs会话的所有其他状态。
另请参阅Clojure Google组的这些讨论:
I am new to Clojure, and am beginning to experiment with building an application.
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.
I am so used to the edit-compile-run idioms of languages like C or Delphi, that I am instinctively driven to make edits, then hit "M-x compile".
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.
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.
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.
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.
So here is my question: any resources for good information or tutorials on the entire process of building a Clojure application, including deployment?
(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:
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.
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!
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.)
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.
See also these discussions on the Clojure Google group:
- Clojure for system administration
- Prepping clojure for packaging (was: Re: Clojure for system administration)
- Leiningen, Clojure and libraries: what am I missing?
这篇关于构建和部署Clojure应用程序的最佳做法:好的教程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!