Какая разница между Cake и Leiningen?
Какая разница между Cake и Leiningen?
Ответ 1
Этот ответ продолжает интересоваться, по-видимому, как ссылка для Leiningen в StackOverflow, поэтому теперь он значительно отредактирован, чтобы обновить его на 2014 год.
Leiningen и Cake объединились еще в 2011 году. Leiningen (версия 2) теперь является инструментом автоматизации de facto Clojure.
Leiningen - это инструмент построения и менеджер зависимостей для Clojure, который включает в себя возможность настройки интерактивного REPL с соответствующим образом настроенным classpath и со всеми зависимостями java и Clojure, полученными автоматическим способом из хранилищ maven и/или сообщества Clojars.
Cake был очень похож на Leiningen (вплоть до использования того же формата файла project.clj в то время), но попытался избежать множества накладных расходов на запуск, сохранив постоянный JVM в фоновом режиме. Это было более отзывчивым, но торговым удобством для ошибок из-за накопленного состояния в постоянных процессах (старые определения функций, зависающие вокруг и т.д.) Над типичным курсом итеративной разработки на основе REPL. Это оказалось плохой сделкой.
Опыт работы с Leiningen и постоянное стремление к более быстрому запуску привели к ряду рекомендаций и подходов к ускорению: https://github.com/technomancy/leiningen/wiki/Faster
Ответ 2
Основное отличие заключается в том, как выполняются задачи.
Подход к выпечке "трудно расширить функции после того, как они были определены, поэтому давайте придумать новый механизм для задач, а не использовать функции", в результате чего появился макрос deftask.
Подход Leiningen заключается в том, что "трудно расширять функции после того, как они были определены, поэтому мы должны сделать так, чтобы сделать это легко: таким образом мы можем использовать функции для задач, а также иметь возможность распространять вещи, которые не являются задачами," который позволяет применять все возможности для удобства использования функций с задачами.Ответ 3
Как отметил Алекс, самым ярким отличием является скорость от командной строки. Cake использует постоянную JVM, поэтому вы впервые сталкиваетесь с накладными расходами jvm при первом запуске задачи в своем проекте. Если вы не используете emacs + slime + clojure -test-mode, это может быть огромное время. Например, достаточно большой набор тестов для одного из моих проектов выполняется в 0,3 секунды в торт, против 11,2 с в лейне.
Помимо производительности, основной идеей торта является модель задачи зависимости. Каждая задача выполняется только один раз в заданной сборке, принимая во внимание все переходные предпосылки в графике зависимостей. Вот пример из статьи Мартина Фаулера о рейке в синтаксисе торта, который идет непосредственно в ваш 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.
ЦСИ/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...
Но и загрузка данных, и моя компиляция зависят от кода-gen, поэтому ваш фактический вывод...
generating code...
compiling...
generating code...
loading test data...
running tests...
Вам нужно будет memoize 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...
Это то, что мы хотим.
Сборка проще и эффективнее, если задача выполняется только один раз для сборки, поэтому мы сделали это по умолчанию в сборках торта. Философия десятилетий назад и разделена линейкой инструментов построения. Вы все еще можете использовать функции, вы все равно можете называть их повторно, и у вас всегда есть полная мощность 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
и использовать их во всех ваших проектах. Глобальный проект также используется для запуска замены вне проекта для экспериментов. Lein реализует аналогичные функции, поддерживая конфигурацию для каждого пользователя в ~/.lein/init.clj
и глобальные плагины в ~/.lein/plugins
. В общем, у Lein в настоящее время гораздо богаче плагиновая экосистема, чем торт, но торт включает в себя больше задач из коробки (война, развертывание, компиляция Java, собственные зависимости, клоары и swank). Cljr также может стоить проверить, это, по сути, всего лишь глобальный проект с менеджером пакетов, но без возможностей сборки (но у меня нет опыта с ним).
Настоящая необратимая разница - это задачи, как указывала техномантия. По моему (предвзятому) мнению, торты обрабатывают задачи намного лучше. Потребность в модели зависимостей задачи стала очевидной, когда мы начали использовать буферы протокола в нашем проекте с lein. Протобуфы были предпосылками для всех наших задач, но их сборка очень медленная. У нас также много взаимозависимых задач, поэтому любая сборка была болезненной. Мне также не нравится требование отдельного пространства имен и, следовательно, дополнительный файл src для каждой задачи, которую я создаю. Разработчики должны создавать множество задач, подход лейн препятствует этому, создавая слишком много трений. С тортом вы можете просто использовать макрос deftask в project.clj.
Торт еще молод и продолжается, но это очень активный проект.
Ответ 4
Как 2011-11-15, объявление слияние торта и лейна