Подтвердить что ты не робот

Какая разница между Cake и Leiningen?

Какая разница между Cake и Leiningen?

4b9b3361

Ответ 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.

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