В чем разница между Cake и Leiningen?


в чем разница между Cake и Leiningen?

4 51

4 ответа:

этот ответ продолжает вызывать интерес, предположительно, как ссылка на Leiningen в StackOverflow, поэтому теперь он значительно отредактирован, чтобы обновить его для 2014 года.

Лейнинген и торт слились еще в 2011 году. Leiningen (версия 2) теперь де-факто инструмент автоматизации Clojure.

Leiningenэто инструмент сборки и менеджер зависимостей для Clojure, который включает в себя возможность настроить интерактивный REPL с соответствующим образом настроенным classpath и со всеми зависимости java и clojure, полученные в автоматическом режиме из репозиториев maven и / или сообщества на основе Clojars.

торт был очень похож на Leiningen (вплоть до использования того же проекта.формат файла clj в то время), но попытался избежать больших накладных расходов при запуске, сохраняя постоянные JVMs в фоновом режиме. Это было более отзывчивым, но торговало удобством для ошибок из-за накопленного состояния в постоянных процессах (старые определения функций висят вокруг и т. д.) в течение типичного курса итеративной разработки на основе REPL. Это оказалось невыгодно.

опыт работы с Leiningen и постоянное стремление к более быстрому запуску привели к ряду рекомендаций и подходов для ускорения работы:https://github.com/technomancy/leiningen/wiki/Faster

основное отличие заключается в способе реализации задач.

подход Cake заключается в том, что "трудно расширить функции после их определения, поэтому давайте придумаем новый механизм для задач, а не использовать функции", что привело к макро deftask.

подход Лейнингена: "трудно расширить функции после того, как они были определены, поэтому мы должны сделать способ сделать это легко; таким образом, мы можем использовать функции для задач, а также иметь возможность расширять вещи, которые не являются задачи", которая позволяет применять все преимущества композиционности функций с задачами.

как уже упоминал Алекс, самое поразительное отличие-это скорость из командной строки. Cake использует постоянную JVM, поэтому вы сталкиваетесь с накладными расходами запуска jvm только при первом запуске задачи в вашем проекте. Если вы не используете emacs + slime + clojure-test-mode, это может быть огромная экономия времени. Например, достаточно большой набор тестов на одном из моих проектов выполняется за 0.3 секунды в cake, против 11.2 s в lein.

кроме представления, идея сердечника за тортом модель задачи зависимостей. Каждая задача выполняется только один раз в данной сборке с учетом всех транзитивных предпосылок в графе зависимостей. Вот пример из статья Мартина Фаулера о граблях в синтаксисе торта, который идет непосредственно в вашем проекте.clj по.

(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, вам сначала нужно будет создать каталог leiningen в вашем проекте с 4 файлами: code_gen.clj, compile.clj, data_load.clj, и мой тест.clj по.

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...

вам придется запомнить код-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...

что мы хотим.

сборки проще и эффективнее, если задача выполняется только один раз за сборку, поэтому мы сделали это поведение по умолчанию в сборках cake. Философия насчитывает десятилетия и разделяется родословной инструментов сборки. Вы все еще можете использовать функции, вы все еще можете вызывать их повторно, и у вас всегда есть полная мощность clojure в вашем распоряжении.

Lein просто дает вам простую функцию как задача, но с добавленным ограничением, что он должен иметь свое собственное пространство имен в src. Если задача зависит от него, она будет находиться в отдельном пространстве имен и должна использовать/требовать другого в нем ns макрос. Торт строит выглядеть гораздо аккуратнее и лаконичнее в сравнении.

еще одно ключевое отличие заключается в том, как задачи добавляются. Допустим, мы хотели добавить my-test, как необходимое условие для торта/Лейн, построенный в jar задач. В торт, вы можете использовать deftask макрос для добавления к формам задачи и зависимости.

(deftask jar #{my-test})

Лейн использует Роберта Гука для добавления к задачам. Это действительно классная библиотека, названная в честь любимого всеми естествоиспытателя, но для краткости deftask.

(add-hook #'leiningen.jar/jar (fn [f & args]
                                (my-test)
                                (apply f args)))

торт также имеет понятие глобального проекта. Вы можете добавить пользовательские dev-зависимости, такие как swank, в ~/.cake/project.clj и имеют его во всех ваших проектах. Глобальный проект также используется для запуска repl вне проекта для экспериментирование. Lein реализует аналогичные функции, поддерживая конфигурацию для каждого пользователя в ~/.lein/init.clj, и глобальные Плагины ~/.lein/plugins. В целом, Lein в настоящее время имеет гораздо более богатую экосистему плагинов, чем cake, но cake включает в себя больше задач из коробки (война, развертывание, компиляция java, собственные зависимости, clojars и swank). Cljr также может быть стоит проверить, это по сути просто глобальный проект с менеджером пакетов, но без возможностей сборки (у меня нет опыта работы с ним, однако).

реальная непримиримая разница-это определения задач, как указала техномантия. По моему (предвзятому) мнению, торт справляется с задачами намного лучше. Необходимость в модели зависимости от задачи стала очевидной, когда мы начали использовать буферы протокола в нашем проекте с lein. Протобуфы были предпосылками для всех наших задач, но их компиляция очень медленная. У нас также есть много взаимозависимых задач, поэтому любая сборка была болезненной. Мне тоже не нравится требование отдельного пространства имен, и поэтому дополнительный src-файл для каждой задачи, которую я создаю. Разработчики должны создать много задач, подход Лейна препятствует этому, создавая слишком много трений. С помощью cake вы можете просто использовать макрос deftask в проекте.clj по.

торт еще молод, и работа идет, но это очень активный проект.

Как 2011-11-15, объявления торт и Лейн слияния