CakeとLeiningenの違いは何ですか?
4 に答える
この回答は、おそらくStackOverflowのLeiningenのリファレンスとして引き続き関心を集めているため、2014年に更新するために大幅に編集されています。
LeiningenとCakeは2011年に統合されました。Leiningen(バージョン2)は、事実上のClojure自動化ツールになりました。
LeiningenはClojureのビルドツールおよび依存関係マネージャーであり、適切に構成されたクラスパスと、MavenリポジトリーやコミュニティベースのClojarから自動化された方法で取得されたすべてのJavaおよびClojure依存関係を使用してインタラクティブREPLをセットアップする機能が含まれています。
CakeはLeiningenと非常に似ていましたが(当時は同じproject.cljファイル形式を使用していました)、永続的なJVMをバックグラウンドに保持することで、多くの起動オーバーヘッドを回避しようとしました。これはより応答性が高かったが、反復REPLベースの開発の典型的な過程で永続的なプロセス(古い関数定義がぶら下がっているなど)に蓄積された状態のため、バグと引き換えに便利でした。これは悪い掘り出し物であることが判明しました。
Leiningenの経験と、起動時間を短縮したいという継続的な要望により、処理を高速化するための多くの推奨事項とアプローチが生まれました:https ://github.com/technomancy/leiningen/wiki/Faster
主な違いは、タスクの実装方法にあります。
Cakeのアプローチは、「関数を定義した後で拡張するのは難しいので、関数を使用するのではなく、タスクの新しいメカニズムを発明しましょう」というもので、deftaskマクロが作成されました。
Leiningenのアプローチは、「関数を定義した後で拡張するのは難しいので、これを簡単に行う方法を作成する必要があります。そうすれば、関数をタスクに使用でき、タスクではないものも拡張できます」。関数の構成可能性の利点をすべてタスクに適用できます。
アレックスが述べたように、最も顕著な違いはコマンドラインからの速度です。Cakeは永続的なJVMを使用するため、プロジェクト内で初めてタスクを実行するときにのみ、jvmの起動オーバーヘッドが発生します。emacs + Slime + clojure-test-modeを使用していない場合、これは大幅な時間の節約になります。たとえば、私のプロジェクトの1つでのかなり大きなテストのセットは、ケーキでは0.3秒で実行されますが、ラインでは11.2秒で実行されます。
パフォーマンスは別として、ケーキの背後にある中心的なアイデアは依存関係タスクモデルです。各タスクは、依存関係グラフのすべての推移的な前提条件を考慮して、特定のビルドで1回だけ実行されます。これは、project.cljに直接含まれるケーキ構文のレーキに関するMartinFowlerの記事の例です。
(deftask code-gen
"This task generates code. It has no dependencies."
(println "generating code...")
...)
(deftask compile #{code-gen}
"This task does the compilation. It depends on code-gen."
(println "compiling...")
...)
(deftask data-load #{code-gen}
"This task loads the test data. It depends on code-gen."
(println "loading test data...")
...)
(deftask test #{compile data-load}
"This task runs the tests. It depends on compile and data-load."
(println "running tests...")
...)
Leiningenで同じことを行うには、最初に、code_gen.clj、compile.clj、data_load.clj、およびmy_test.cljの4つのファイルを使用してプロジェクトにleiningenディレクトリを作成する必要があります。
src / leiningen / code_gen.clj
(ns leiningen.code-gen
"This task generates code. It has no dependencies.")
(defn code-gen []
(println "generating code..."))
src / leiningen / my_compile.clj
(ns leiningen.my-compile
"This task does the compilation. It depends on code-gen."
(:use [leiningen.code-gen]))
(defn my-compile []
(code-gen)
(println "compiling..."))
src / leiningen / data_load.clj
(ns leiningen.data-load
"This task loads the test data. It depends on code-gen."
(:use [leiningen.code-gen]))
(defn data-load []
(code-gen)
(println "loading test data..."))
src / leiningen / my_test.clj
(ns leiningen.my-test
"This task runs the tests. It depends on compile and data-load."
(:use [leiningen.my-compile]
[leiningen.data-load]))
(defn my-test []
(my-compile)
(data-load)
(println "running tests..."))
期待するだろう...
generating code...
compiling...
loading test data...
running tests...
ただし、data-loadとmy-compileはどちらもcode-genに依存しているため、実際の出力は...
generating code...
compiling...
generating code...
loading test data...
running tests...
code-genが複数回実行されないようにするには、code-genをメモ化する必要があります。
(ns leiningen.code-gen
"This task generates code. It has no dependencies.")
(def code-gen (memoize (fn []
(println "generating code..."))))
出力:
generating code...
compiling...
loading test data...
running tests...
それが私たちが望んでいることです。
タスクがビルドごとに1回だけ実行される場合、ビルドはより単純で効率的であるため、ケーキビルドのデフォルトの動作にしました。哲学は数十年前のものであり、一連のビルドツールによって共有されています。関数は引き続き使用でき、繰り返し呼び出すことができ、いつでもclojureの全機能を自由に使用できます。
Leinは、タスクとして単純な関数を提供するだけですが、srcに独自の名前空間が必要であるという制約が追加されています。タスクがそれに依存している場合、それは別の名前空間にあり、そのns
マクロで他の名前空間を使用/要求する必要があります。ケーキのビルドは、比較するとはるかにすっきりと簡潔に見えます。
もう1つの重要な違いは、タスクの追加方法です。my-test
ケーキ/ラインの組み込みタスクの前提条件として追加したいとしjar
ます。ケーキでは、deftask
マクロを使用してタスクのフォームと依存関係に追加できます。
(deftask jar #{my-test})
LeinはRobertHookeを使用してタスクに追加します。みんなのお気に入りの自然哲学者にちなんで名付けられた、本当にクールなライブラリですが、簡潔にするためにマクロが必要になりますdeftask
。
(add-hook #'leiningen.jar/jar (fn [f & args]
(my-test)
(apply f args)))
Cakeには、グローバルプロジェクトの概念もあります。swankなどのユーザー固有の開発依存関係を追加し~/.cake/project.clj
て、すべてのプロジェクトに適用できます。グローバルプロジェクトは、実験のためにプロジェクトの外部でreplを開始するためにも使用されます。Leinは、でユーザーごとの構成をサポートし~/.lein/init.clj
、でグローバルプラグインをサポートすることで、同様の機能を実装しています~/.lein/plugins
。一般に、Leinは現在、Cakeよりもはるかに豊富なプラグインエコシステムを備えていますが、Cakeには、すぐに使用できるタスク(war、deploy、javaコンパイル、ネイティブ依存関係、clojar、swank)が多く含まれています。Cljrもチェックする価値があるかもしれません。これは基本的に、パッケージマネージャーを備えた単なるグローバルプロジェクトですが、ビルド機能はありません(ただし、経験はありません)。
テクノマンシーが指摘したように、本当の矛盾する違いはタスクの定義です。私の(偏った)意見では、ケーキはタスクをはるかにうまく処理します。プロジェクトでleinを使用してプロトコルバッファを使用し始めたときに、タスク依存関係モデルの必要性が明らかになりました。Protobufsは、すべてのタスクの前提条件でしたが、コンパイルには非常に時間がかかります。また、相互に依存するタスクがたくさんあるため、ビルドは面倒でした。また、作成するすべてのタスクに対して、個別の名前空間、つまり追加のsrcファイルが必要になることも好きではありません。開発者は多くのタスクを作成する必要があります。leinのアプローチは、あまりにも多くの摩擦を作成することによってこれを思いとどまらせます。ケーキを使用すると、project.clj内でdeftaskマクロを使用できます。
Cakeはまだ若く、作業が進行中ですが、非常に活発なプロジェクトです。
2011年 11月15日、ケーキとラインの発表が合併