В чем разница между Cake и Leiningen? - PullRequest
51 голосов
/ 11 октября 2010

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

Ответы [ 4 ]

48 голосов
/ 11 октября 2010

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

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

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

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

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

24 голосов
/ 11 октября 2010

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

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

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

20 голосов
/ 15 октября 2010

Как уже упоминал Алекс, самое разительное отличие - скорость от командной строки. Cake использует постоянную JVM, поэтому вы сталкиваетесь с издержками запуска jvm только при первом запуске задачи в своем проекте. Если вы не используете emacs + slime + clojure-test-mode, это может значительно сэкономить время. Например, достаточно большой набор тестов в одном из моих проектов выполняется за 0,3 секунды в тесте против 11,2 с в Lein.

Помимо производительности, основной идеей торта является модель задачи зависимости. Каждая задача запускается только один раз в данной сборке с учетом всех переходных предпосылок в графе зависимостей. Вот пример из статьи Мартина Фаулера о рейке в синтаксисе тортов, которая идет прямо в ваш project.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 и my_test.clj.

SRC / Leiningen / code_gen.clj

(ns leiningen.code-gen
   "This task generates code. It has no dependencies.")

(defn code-gen []
  (println "generating code..."))

ЦСИ / 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..."))

ЦСИ / 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..."))

ЦСИ / 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...

Но как загрузка данных, так и my-compile зависят от кода-генерации, поэтому ваш фактический вывод ...

generating code...
compiling...
generating code...
loading test data...
running tests...

Вам нужно будет запомнить 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...

Что мы и хотим.

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

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

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

(deftask jar #{my-test})

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

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

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

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

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

7 голосов
/ 30 ноября 2011

Как 2011-11-15, объявление сливки с пирожными и лейн

...