Jaka jest różnica między Cake a Leiningen?Jaka jest różnica między Cake a Leiningen?
Odpowiedz
Ta odpowiedź kontynuuje się zainteresowanie, przypuszczalnie jako punkt odniesienia dla Leiningen w StackOverflow tak jest teraz znacznie edytowany zaktualizować ją do 2014
Leiningen i ciasto połączone z powrotem w 2011. Leiningen (wersja 2) jest teraz de facto narzędzie automatyzacji Clojure.
Leiningen jest narzędziem budowania i menedżer zależność dla Clojure który obejmuje zdolność do utworzenia interaktywnego rEPL z odpowiednio skonfigurowanym ścieżce klasy i ze wszystkimi zależnościami Javie i Clojure nabytych w sposób zautomatyzowany z repozytorium maven i/lub społeczności opartych Clojars.
Ciasto było bardzo podobne do Leiningen (do używania tego samego formatu pliku project.clj w tym czasie), ale starało się uniknąć wielu kosztów uruchomienia, utrzymując trwałe maszyny JVM w tle. Było to bardziej responsywne, ale wygodniejsze w handlu dla błędów ze względu na nagromadzony stan w trwałych procesach (stare definicje funkcji, itp.) W typowym przebiegu iteracyjnego rozwoju opartego na REPL. Okazało się, że to zła okazja.
Doświadczenie z Leiningen i ciągłego pragnienia szybszych czasów startowych mają prowadzić do szeregu zaleceń i podejść dla przyspieszenia rzeczy: https://github.com/technomancy/leiningen/wiki/Faster
Główną różnicą jest sposób zadania są wykonywane.
Podejście do ciasta polega na tym, że "trudno jest rozszerzyć funkcje po ich zdefiniowaniu, więc wymyślmy nowy mechanizm zadań, zamiast korzystać z funkcji", co spowodowało makro deftask. Podejście Leiningena polega na tym, że "trudno jest rozszerzyć funkcje po ich zdefiniowaniu, więc powinniśmy zrobić to w prosty sposób, w ten sposób możemy wykorzystać funkcje do zadań, a także być w stanie rozszerzyć rzeczy, które nie są zadania ", co pozwala zastosować wszystkie zalety kompozycyjności funkcji z zadaniami.
Czy chciałbyś podać przykład? Nie jestem bardzo zaznajomiony z Leiningenem i Cakeem, i byłbym zainteresowany, aby zobaczyć ilustrację różnicowania, które opisujesz między tymi dwoma. –
Gdy zadania są po prostu funkcjami, możesz je rozszerzyć na wiele ciekawszych sposobów. Śledź tę wtyczkę Leiningen: http://github.com/technomancy/rodney-leonard-stubbs Rozszerzenie zadania Cake pozwala tylko na dołączanie/kontynuowanie efektów ubocznych, podczas gdy Leiningen pozwala na ponowne wiązanie, zmianę argumentów/wartości zwracanych i wykonanie warunkowe. – technomancy
Zadania ciast mogą zawierać również wywołania funkcji, obsługujące wszystkie te funkcje. – lancepantz
Jak wspomniał Alex, najbardziej uderzającą różnicą jest prędkość z wiersza poleceń. Ciasto używa trwałej maszyny JVM, więc napotkasz jedynie na obciążenie startowe jvm, gdy po raz pierwszy uruchamiasz zadanie w swoim projekcie. Jeśli nie używasz emacs + slime + tryb testowy clojure, może to być ogromny czas. Na przykład rozsądnie duży zestaw testów w jednym z moich projektów przebiega w 0,3 sekundy w placku, a 11,2 w w leinie.
Oprócz wydajności podstawową ideą ciasta jest model zadania zależności. Każde zadanie jest uruchamiane tylko raz w danej kompilacji, biorąc pod uwagę wszystkie przejściowe wymagania wstępne na wykresie zależności. Oto przykład z Martin Fowler's article on rake w składni ciasta, który jest bezpośrednio w twoim projekcie.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...")
...)
Aby zrobić to samo w Leiningen, to najpierw trzeba utworzyć katalog Leiningen w projekcie z 4 plików: code_gen.clj, compile.clj, data_load.clj i 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..."))
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..."))
Jeden spodziewałbym ...
generating code...
compiling...
loading test data...
running tests...
Ale zarówno dane obciążenia i my-kompilacji zależy od kodu-gen, więc aktualny adres to ...
generating code...
compiling...
generating code...
loading test data...
running tests...
Yo u musiałyby memoize code-gen, aby zapobiec jej uruchomić wiele razy:
(ns leiningen.code-gen
"This task generates code. It has no dependencies.")
(def code-gen (memoize (fn []
(println "generating code..."))))
wyjściowa:
generating code...
compiling...
loading test data...
running tests...
co jest, co chcemy.
Kompilacje są prostsze i bardziej wydajne, jeśli zadanie jest uruchamiane tylko raz na kompilację, więc zrobiliśmy to domyślne zachowanie w kompilacjach ciastek. Filozofia ma kilkadziesiąt lat i jest dzielona przez linię narzędzi do budowania. Nadal możesz korzystać z funkcji, wciąż możesz do nich dzwonić wielokrotnie i zawsze masz do dyspozycji pełną moc clojure.
Lein daje prostą funkcję jako zadanie, ale z dodanym ograniczeniem, że musi mieć własną przestrzeń nazw w src. Jeśli zadanie zależy od tego, będzie ono w oddzielnym obszarze nazw i musi używać/wymagać drugiego w jego makrze ns
. Konstrukcje tortów wyglądają znacznie bardziej schludnie i zwięźle w porównaniu.
Inną kluczową różnicą jest to, w jaki sposób dołączane są zadania. Powiedzmy, że chcemy dodać my-test
jako warunek wstępny zadania cake/lein w jar
. W ciastku można użyć makra deftask
do dołączenia do formularzy i zależności zadania.
(deftask jar #{my-test})
Lein używa Roberta Hooke'a do dołączania do zadań. To naprawdę fajna biblioteka, nazwana tak na cześć wszystkich ulubionych filozofów przyrody, ale wymagałaby ona makra ze zwięzłością deftask
.
(add-hook #'leiningen.jar/jar (fn [f & args]
(my-test)
(apply f args)))
Ciasto ma również pojęcie projektu globalnego. Możesz dodawać zależne od użytkownika zależności od dev, takie jak swank, do ~/.cake/project.clj
i mieć je we wszystkich swoich projektach. Projekt globalny służy również do uruchamiania replik poza projektem do eksperymentów. Lein implementuje podobne funkcje, wspierając konfigurację poszczególnych użytkowników w ~/.lein/init.clj
i globalne wtyczki w ~/.lein/plugins
. Ogólnie rzecz biorąc, Lein ma obecnie znacznie bogatszy ekosystem wtyczki niż ciastko, ale ciasto zawiera więcej zadań poza pakietem (wojna, wdrożenie, kompilacja java, natywne zależności, clojars i swank). Cljr również może być warty sprawdzenia, jest to po prostu projekt globalny z menedżerem pakietów, ale bez możliwości kompilacji (nie mam z tym żadnego doświadczenia).
Prawdziwą, niezwyciężoną różnicą są definicje zadań, jak wskazała technika. W mojej (stronniczej) opinii, tort radzi sobie z zadaniami o wiele lepiej. Zapotrzebowanie na model zależności od zadań stało się oczywiste, gdy zaczęliśmy używać buforów protokołu w naszym projekcie z leinem. Protobufy były wstępnymi warunkami dla wszystkich naszych zadań, jednak ich kompilacja jest bardzo powolna. Mamy również wiele zadań zależnych od siebie, więc każda kompilacja była bolesna. Nie podoba mi się także wymaganie oddzielnego obszaru nazw, a zatem dodatkowego pliku src, dla każdego zadania, które tworzę.Deweloperzy powinni tworzyć wiele zadań, podejście Lein'a zniechęca do tego, tworząc zbyt duże tarcie. Z ciastem możesz po prostu użyć makra deftask w project.clj.
Ciasto jest wciąż młode, a produkcja w toku, ale jest to bardzo aktywny projekt.
Istnieje również "lein interactive", który pozwala uruchamiać ciągły lein bez narzutu czasu uruchamiania java dla każdego polecenia lein. – Marko
Ten czterozadaniowy przykład jest dość wymyślny. Robimy to w ten sposób, ponieważ make nie ma funkcji, więc wszystko musi być zadaniem. Ale nigdy nie rozdzieliłbyś swoich zadań w ten sposób z Leiningen; to po prostu nie ma sensu. Nigdy nie widzisz zadań, które są tak krótkie; w praktyce jest zawsze co najmniej 2 lub 3 funkcje pomocnicze w przestrzeni nazw tego zadania. – technomancy
Sprzeciw wobec Roberta Hooke'a jest również bardzo głupi; Zaimplementowałem makro prepend w czterech liniach, aby zrobić to, co robią zalążki Cake. Najtrudniejszą częścią było wybranie nazwy makra. – technomancy
jako 2011-11-15, ogłoszenie cake and lein merge
Najprawdopodobniej usunięto grupę klamerek. Inny link do ogłoszenia nadal działa: https://groups.google.com/forum/#!topic/leiningen/WnnQIZipG5E – Joanis
placek w trakcie połączenia z Leiningen. Link: https://groups.google.com/forum/#!topic/leiningen/WnnQIZipG5E – Joanis