Jeśli Java jest językiem ogólnego przeznaczenia, a budowanie programu jest czymś, co można opisać za pomocą języka Java, dlaczego nie jest to najlepszy sposób pisania plików kompilacji, a zamiast tego używamy narzędzi takich jak Ant, Maven i Gradle? Czy nie byłoby to prostsze, a także nie wymagałoby nauki kolejnego języka programowania? (BTW - to pytanie można również zastosować do innych języków, takich jak C #)
java
c#
builds
build-system
vainolo
źródło
źródło
Odpowiedzi:
Określone narzędzie do określonego celu
Gadatliwość
Języki ogólnego przeznaczenia są często zbyt szczegółowe. Gdybym miał zarządzać kompilacją w Javie, bardzo szybko wpadłbym w depresję ze względu na rozmiar bestii. Można go jednak łatwo zarządzać za pomocą DSL napisanego w Javie. I do pewnego stopnia tak można zobaczyć Gradle (dla Groovy) i Buildr (dla Ruby).
Trudność
Języki ogólnego przeznaczenia są trudne. Cóż, nie sądzę, aby programowanie było trudne i nie mogło być odebrane przez nikogo, ale chodzi o to, że inżynier budowy niekoniecznie jest twoim programistą!
Cel, powód
To mniej więcej na styku trudności i gadatliwości . Język został zaprojektowany w określonym celu, a tutaj mówimy o czymś bardzo specyficznym. Dlaczego więc miałbyś chcieć używać języka ogólnego ? Do kompilacji potrzebujesz:
Tak naprawdę nie potrzebujesz dużo więcej.
Na pewno jest denerwujące, gdy wydaje się, że twój system kompilacji nie jest wystarczająco elastyczny dla tego jednego specjalnego zastosowania, którego szukasz, ale prawdopodobnie jest znacznie lepszy niż alternatywa dla większości ludzi.
Prawdopodobnie dlatego istnieje polaryzacja między osobami, które wolą deklaratywne systemy kompilacji niż większość programowalnych jednostek: Myślę, że deweloper może mieć naturalną tendencję do szukania sposobów wyjścia z pudełka.
Czekaj, czy naprawdę potrzebujemy narzędzia?
Kolejne powiązane pytanie brzmi: czy naprawdę potrzebujemy narzędzia do kompilacji? Czy fakt, że istnieją we wszystkich językach, nie jest znakiem, że wypełniają lukę, której w ogóle nie powinno być w ogóle?
Niektóre języki niekoniecznie wymagają narzędzia do kompilacji. Na przykład większość języków skryptowych nie potrzebuje jednego i jest rozwiązywana w czasie ładowania. Albo weź Go, którego kompilator poradzi sobie z wszystkim, co jest fajnym kontrapunktem: co, jeśli kompilator taki jak gcc nagle nie potrzebuje wiązki flag, linkera i makefile, aby umrzeć razem? A jeśli javac nie potrzebuje pliku build.xml lub pom.xml, aby powiedzieć mu, co ma robić? Czy zarządzanie zależnościami nie powinno być bezpośrednio częścią własnego narzędzia języka, ponieważ zależności są częścią końcowego programu?
Z pewnością wygląda to na znacznie prostsze podejście dla użytkownika (konstruktora). Choć można argumentować, że robią to pod maską i zabierają ci wybór i możliwości wpływania na proces kompilacji (ale masz nadzieję, że takie narzędzie pozwala na rozszerzenia kompilatora i podobne rzeczy). Poza tym postrzegaliśmy narzędzia i język jako dwie odrębne rzeczy, więc może wydawać się nieczystym, że nagle ma tak ściśle powiązane.
Nie sądzę, że język, którym używasz do tworzenia programów, jest problemem. To język, którego używasz do programowania, jego podstawowa platforma i narzędzia, które powinny mieć znaczenie, a my wciąż robimy postępy.
Osobiście użyłem make / gmake / autotools / pmk i byłem zadowolony z nich dla C, i zacząłem od Javy, kiedy wszystko, co mieliśmy, było potem, a potem mrówka, a teraz ogólnie wolę Maven od wszystkich tych alternatyw. Chociaż widzę wartość w stopniach, budowniczych i innych, ale jak dotąd podoba mi się przewaga maven, dopóki nie nastąpi bardziej znacząca zmiana. Ponadto podoba mi się to , że jest sztywny, ale nadal pozwala ci obejść to w razie potrzeby. To, że to nie jest łatwe, jest dobrą rzeczą.
To narzędzie do budowania. Naucz się go obejmować i nie walcz z nim. To przegrana bitwa. A przynajmniej bardzo długi.
źródło
Java
Jest to konieczne, język,Ant
,Maven
, itd. są deklaratywne w językach:Języki kompilacji mówią konstruktorowi, co należy zrobić, skąd należy go wziąć itp. Silnik, który uruchamia kompilację (napisany w języku rozkazującym, jak zauważył @ElliottFrisch), czyta te instrukcje i je wypełnia.
Języki deklaratywne mogą wydawać się bardziej odpowiednie w scenariuszach kompilacji, ponieważ zadania kompilacji są ogólnie takie same i uważa się je za łatwiejsze w utrzymaniu i czytelne w tej formie niż w pełnoprawnej formie kodu.
źródło
Jeśli spojrzysz na funkcje typowego systemu kompilacji, znajdziesz:
Jeśli zamierzasz napisać serię plików kompilacji przy użyciu jakiegoś języka (Java / C # / Python / etc), mniej więcej w trzeciej lub czwartej iteracji zdecydowałbyś się na (a) zachowanie większości danych i poleceń zewnętrznych jako danych w czymś jak XML (b) pisanie „silnika kompilacji” w twoim ulubionym języku.
Przydatne byłoby również traktowanie niektórych danych w pliku XML jako języka interpretowanego w celu uruchomienia różnych funkcji silnika kompilacji. Możesz również zinterpretować niektóre makra lub wykonać zamiany ciągów w danych.
Innymi słowy, skończyłbyś z Make, lub Ant, Rake lub MsBuild. Niezbędny język dla tego, co robi dobrze, i struktury danych opisujące to, co chcesz zrobić, teraz zwykle w formacie XML.
źródło
W takich przypadkach wiele czynników nie pozwala na użycie Java / C ++ / C #.
Po pierwsze, musisz skompilować skrypt kompilacji, zanim będziesz mógł go uruchomić, aby zbudować aplikację. Jak określiłbyś jakieś pakiety, flagi, wersje kompilatora, ścieżki narzędzi potrzebne do zbudowania skryptu kompilacji? Z pewnością możesz wymyślić sposób na obejście tego, ale o wiele prostsze jest posiadanie języka, który nie potrzebuje tego kroku kompilacji (np. Python), lub języka, który natywnie rozumie twoje narzędzie do budowania.
Po drugie, pliki kompilacji są obciążone danymi, podczas gdy Java / C ++ / C # są znacznie bardziej ukierunkowane na pisanie kodu i algorytmów. Java i przyjaciele nie mają zwięzłej reprezentacji wszystkich danych, które chcesz przechowywać.
Po trzecie, Java i przyjaciele potrzebują dużej ilości boksów, aby były ważne. Plik kompilacji musiałby znajdować się w metodzie wewnątrz klasy z wszystkimi jej importami. Korzystając z języka skryptowego lub niestandardowego, możesz uniknąć całego tego schematu i po prostu mieć same szczegóły kompilacji.
źródło
W rzeczy samej! Dlaczego nie użyć mocnego i wyrazistego języka dla problemu, który jest bardziej złożony niż ludzie (na początku) często myślą? Zwłaszcza gdy osoby, które borykają się z tym problemem, są już kompetentne w takim języku. (Budowanie jest własnym problemem programistów i najlepiej rozwiązane przez programistów.)
Zadałem sobie to pytanie wiele lat temu i zdecydowałem, że Java jest dobrym językiem do definiowania kompilacji, szczególnie dla projektów Java. W rezultacie zacząłem coś z tym robić.
ZASTRZEŻENIE : W tej odpowiedzi promuję iwant , system kompilacji, który rozwijam. Ale skoro i tak jest to dyskusyjna dyskusja, jestem pewien, że jest w porządku.
Nie będę omawiać korzyści płynących z Javy (moc i ekspresja), ani konkretnie. Jeśli jesteś zainteresowany, możesz przeczytać więcej na stronie iwant .
Zamiast tego zastanowię się, dlaczego Java (i inne GPL) jest tak łatwo odrzucana, że nie nadaje się do budowania. Wiele odpowiedzi i komentarzy tutaj jest dobrym przykładem takiego myślenia. Rozważmy niektóre z typowych argumentów:
„Java jest niezbędna, ale kompilacje najlepiej definiować w sposób deklaratywny” , mogliby powiedzieć.
Prawdziwe. Ale kiedy używasz języka jako metalajzyka dla wewnętrznej DSL , tak naprawdę liczy się jego składnia . Nawet imperatywny język, taki jak Java, można oszukać, by zadeklarować. Jeśli wygląda i wydaje się deklaratywny, jest (dla celów praktycznych) deklaratywny. Na przykład:
To jest prawdziwy przykład z projektu demo iwant .
W rzeczywistości porównaj to z niektórymi rzekomo deklaratywnymi systemami kompilacji, które narażają swoich użytkowników na tak ważne czasowniki, jak „test” lub „kompilacja”. Powyższa deklaracja zawiera tylko rzeczowniki, bez czasowników. Kompilowanie i testowanie to zadania domyślnie obsługiwane przez iwant w celu zapewnienia użytkownikowi rzeczowników, których on chce. To nie jest język. Tak to wykorzystujesz.
„Java jest pełna”
Tak, dużo kodu Java jest tam gadatliwy. Ale znowu, to nie jest język, tylko sposób, w jaki go używasz. Jeśli implementacja jest pełna, po prostu obuduj ją za ładną abstrakcją. Wiele GPL zapewnia do tego odpowiednie mechanizmy.
Wyobraź sobie powyższy fragment kodu Java napisany w języku XML. Zastąp nawiasy nawiasami kątowymi i przesuwaj je. A następnie zduplikuj każde słowo kluczowe jako tag zamykający! Java jako składnia nie jest pełna.
(Wiem, porównywanie z XML-em jest jak zabieranie cukierków dziecku, ale tak się składa, że tak wiele kompilacji zostało zdefiniowanych w XML).
„Musisz skompilować skrypt kompilacji”
To jest ważny punkt. Niemniej jednak jest to tylko niewielki problem techniczny do rozwiązania. Mógłbym to rozwiązać za pomocą fasolki szparagowej lub innego tłumacza. Zamiast tego rozwiązałem go, traktując go jako kolejny problem z kompilacją i ładując iwant za pomocą prostego skryptu powłoki lub ant, który kompiluje i uruchamia prosty bootstrapper Java.
„Java ma płytę grzewczą”
Prawdziwe. Musisz zaimportować klasy, musisz wspomnieć o „public”, „class” i tak dalej. I tutaj proste zewnętrzne DSL zapewniają początkową łatwą wygraną.
A jeśli twój projekt jest tak trywialny, że ta płyta jest znacząca, gratulacje. Twój problem nie jest trudny i naprawdę nie ma znaczenia, jak go rozwiązać.
Ale wiele projektów wymaga znacznie więcej niż tylko kompilacji, raportu pokrycia i pakowania. Jeśli płyta główna Java jest dopuszczalna w przypadku problemów klientów, dlaczego nie budować problemów? Po co robić buty tylko dla dzieci innych osób?
źródło
Jedną rzeczą, nie sądzę, że inne odpowiedzi dotyczyły tego, że ograniczenia i przejrzystość tych języków kompilacji stanowią ogromną część tego, co czyni je użytecznymi. Weźmy na przykład Maven. Tak, wykonuje kompilacje, ale także definiuje zależności. Pozwala to kompilacji Maven zlikwidować te zależności i spojrzeć na ich zależności i tak dalej.
Zastanów się, czy zrobiono to bezpośrednio z Javą. Narzędzie kompilacji zobaczy, że istnieje zależność. Musiałby wtedy ściągnąć inną aplikację Java i uruchomić ją, aby ustalić, jakie są zależności. Ale dla Maven po prostu patrzy na deklaracje zależności. Plik kompilacji maven jest przezroczysty. Kompletny język Turinga jest z natury nieprzejrzysty i dlatego jest gorszy w niektórych celach, takich jak ten.
źródło