Wenn Java eine Allzwecksprache ist und das Erstellen eines Programms mit Java beschrieben werden kann, warum ist dies nicht die beste Methode, Build-Dateien zu schreiben, und stattdessen verwenden wir Tools wie Ant, Maven und Gradle? Wäre das nicht unkomplizierter und müsste nicht noch eine weitere Programmiersprache erlernt werden? (Übrigens - diese Frage kann auch auf andere Sprachen wie C # angewendet werden.)
java
c#
builds
build-system
vainolo
quelle
quelle
Antworten:
Spezifisches Werkzeug für einen bestimmten Zweck
Ausführlichkeit
Allzwecksprachen sind oft zu ausführlich. Wenn ich einen Build in Java verwalten müsste, wäre ich von der Größe des Tieres sehr schnell sehr deprimiert. Mit einem in Java geschriebenen DSL kann es jedoch problemlos verwaltet werden. Und bis zu einem gewissen Grad sieht man Gradle (für Groovy) und Buildr (für Ruby).
Schwierigkeit
Allzwecksprachen sind schwierig. Nun, ich denke nicht, dass Programmierung schwierig ist und von niemandem aufgegriffen werden kann, aber der Punkt ist: Ihr Build-Ingenieur ist nicht unbedingt Ihr Programmierer!
Zweck
Das ist mehr oder weniger der Schnittpunkt von Schwierigkeit und Ausführlichkeit . Eine Sprache ist für einen Zweck konzipiert, und hier geht es um etwas ganz Bestimmtes. Also warum sollten Sie brauchen oder einen verwenden möchten allgemeine Zweck Sprache? Für Builds benötigen Sie:
Du brauchst nicht wirklich viel mehr.
Sicher, es ist ärgerlich, wenn Ihr Build-System nicht flexibel genug für den speziellen Anwendungsfall ist, den Sie suchen, aber es ist wahrscheinlich weitaus besser als die Alternative für die meisten Menschen.
Das ist wahrscheinlich der Grund, warum Menschen, die deklarative Build-Systeme gegenüber den meisten programmierbaren bevorzugen, eine Polarität haben: Ich denke, ein Entwickler hat eine natürliche Tendenz, nach Wegen zu suchen, um aus der Box auszubrechen.
Warten Sie, brauchen wir wirklich ein Werkzeug?
Eine andere verwandte Frage wäre: Brauchen wir wirklich ein Build-Tool? Ist die Tatsache, dass sie in allen Sprachen existieren, nicht das Zeichen dafür, dass sie eine Lücke füllen, die gar nicht erst vorhanden sein sollte?
Einige Sprachen erfordern nicht unbedingt ein Build-Tool. Beispielsweise benötigen die meisten Skriptsprachen keine und werden beim Laden aufgelöst. Oder nimm Go, dessen Compiler alles für dich erledigt, was ein netter Kontrapunkt ist: Was wäre, wenn ein Compiler wie gcc plötzlich nicht mehr ein paar Flags, einen Linker und ein Makefile bräuchte, um alles zusammen zu sterben? Oder wenn Javac keine build.xml oder pom.xml brauchte, um ihm zu sagen, was er tun soll? Sollte das Abhängigkeitsmanagement nicht direkt Teil der sprachspezifischen Tools sein, da die Abhängigkeiten Teil des endgültigen Programms sind?
Dies scheint für den Benutzer (den Builder) ein viel einfacherer Ansatz zu sein. Man könnte jedoch argumentieren, dass sie sich nur im Verborgenen bewegen und Ihnen die Wahl und die Möglichkeiten nehmen, auf diesen Build-Prozess Einfluss zu nehmen (aber dann würden Sie hoffen, dass ein solches Tool Compiler-Erweiterungen und ähnliches ermöglicht). Außerdem sahen wir die Werkzeuge und die Sprache als zwei getrennte Dinge an, sodass es unsicher erscheinen könnte, wenn sie plötzlich so eng miteinander verbunden sind.
Ich denke nicht, dass die Sprache, die Sie verwenden, um Ihre Programme zu erstellen, das Problem ist. Es ist die Sprache, mit der Sie programmieren, und die Kernplattform und das Kernwerkzeug, die von Bedeutung sein sollten, und wir kommen immer noch voran.
Persönlich habe ich make / gmake / autotools / pmk verwendet und war mit C zufrieden, und ich habe mit Java angefangen, als wir nur make und dann ant hatten, und jetzt bevorzuge ich Maven im Allgemeinen all diesen Alternativen. Obwohl ich Wert in Gradle, Buildr und anderen sehen kann, mag ich die Prävalenz von Maven bis jetzt, bis eine signifikantere Verschiebung eintritt. Außerdem gefällt mir, dass es starr ist, aber es Ihnen trotzdem die Möglichkeit lässt, das bei Bedarf zu umgehen. Dass es nicht einfach ist, ist eine gute Sache.
Es ist ein Build-Tool. Lerne es einfach zu umarmen und bekämpfe es nicht. Es ist eine verlorene Schlacht. Oder zumindest eine sehr, sehr lange.
quelle
Java
ist ein Imperativ SpracheAnt
,Maven
sind usw. deklarativen Sprachen:Build Sprachen sagen die Erbauer , was getan werden sollte, von wo sie getroffen werden sollten, usw. Der Motor, der läuft die Build (die in einer imperativen Sprache geschrieben ist, wie @ElliottFrisch bemerkt hat), liest diese Anweisungen, und erfüllt sie.
Deklarative Sprachen erscheinen in Build-Szenarien möglicherweise angemessener, da Build-Tasks im Allgemeinen überall gleich sind und in dieser Form als wartbarer und lesbarer angesehen werden als in vollständigem Code.
quelle
Wenn Sie sich die Merkmale eines typischen Build-Systems ansehen, finden Sie:
Wenn Sie beabsichtigen, eine Reihe von Build-Dateien in einer bestimmten Sprache (Java / C # / Python / etc) zu schreiben, würden Sie sich ab der dritten oder vierten Iteration darauf einigen, (a) die meisten Daten und externen Befehle als Daten in etwas zu speichern wie XML (b) Schreiben der "Build Engine" in Ihrer Lieblingssprache.
Sie finden es auch nützlich, einige der Daten in Ihrem XML als interpretierte Sprache zu behandeln, um verschiedene Funktionen in der Build-Engine auszulösen. Sie können auch einige Makros interpretieren oder Zeichenfolgensubstitutionen in den Daten durchführen.
Mit anderen Worten, Sie würden mit Make, Ant, Rake oder MsBuild abschließen. Eine zwingende Sprache für die Dinge, die es gut macht, und Datenstrukturen, um zu beschreiben, was Sie tun möchten, jetzt in der Regel in XML.
quelle
In diesen Fällen sprechen eine Reihe von Faktoren gegen die Verwendung von Java / C ++ / C #.
Zunächst müssen Sie Ihr Erstellungsskript kompilieren, bevor Sie es ausführen können, um Ihre App zu erstellen. Wie würden Sie Pakete, Flags, Compilerversionen und Toolpfade angeben, die zum Erstellen Ihres Build-Skripts benötigt werden? Natürlich könnten Sie eine Lösung finden, aber es ist viel einfacher, entweder eine Sprache zu haben, die diesen Build-Schritt nicht benötigt (z. B. Python), oder eine Sprache, die Ihr Build-Tool von Haus aus versteht.
Zweitens sind Build-Dateien datenintensiv, wohingegen Java / C ++ / C # wesentlich stärker auf das Schreiben von Code und Algorithmen ausgerichtet ist. Java und Freunde haben keine sehr prägnante Darstellung aller Daten, die Sie speichern möchten.
Drittens benötigen Java und Freunde eine Menge Boilerplate, um gültig zu sein. Die Build-Datei müsste sich innerhalb einer Methode innerhalb einer Klasse mit all ihren Importen befinden. Wenn Sie eine Skriptsprache oder eine benutzerdefinierte Sprache verwenden, können Sie alles Mögliche vermeiden und haben nur die Build-Details selbst.
quelle
Tatsächlich! Warum nicht eine mächtige und ausdrucksstarke Sprache für ein Problem verwenden, das komplexer ist, als die Leute (anfangs) oft denken? Vor allem, wenn die Betroffenen bereits mit einer solchen Sprache vertraut sind. (Bauen ist das Problem der Programmierer und wird am besten von den Programmierern gelöst.)
Diese Frage habe ich mir auch vor Jahren gestellt und festgestellt, dass Java eine gute Sprache für die Definition von Builds ist, insbesondere für Java-Projekte. Infolgedessen fing ich an, etwas dagegen zu unternehmen.
HAFTUNGSAUSSCHLUSS : In dieser Antwort bewerbe ich iwant , ein Build-System, das ich entwickle. Aber da dies sowieso eine Diskussion mit einer Meinung ist, bin ich mir sicher, dass es in Ordnung ist.
Auf die Vorteile von Java (Leistung und Ausdruckskraft) werde ich nicht näher eingehen. Wenn Sie interessiert sind, können Sie mehr auf der iwant Seite lesen .
Stattdessen werde ich überlegen, warum Java (und andere GPLs) so schnell als ungeeignet für das Bauen abgetan werden. Viele Antworten und Kommentare hier sind gute Beispiele für ein solches Denken. Betrachten wir einige der typischen Argumente:
"Java ist ein Muss, aber Builds lassen sich am besten deklarativ definieren" , könnten sie sagen.
Wahr. Bei der Verwendung einer Sprache als Metasprache für ein internes DSL zählt jedoch die Syntax . Selbst eine imperative Sprache wie Java kann ausgetrickst werden , um deklarativ zu sein. Wenn es deklarativ aussieht und sich deklarativ anfühlt, ist es (aus praktischen Gründen) deklarativ. Beispielsweise:
Dies ist ein echtes Beispiel aus dem Demo-Projekt von iwant .
Vergleichen Sie dies tatsächlich mit einigen vermeintlich deklarativen Buildsystemen, die ihre Benutzer solchen Imperativverben wie "test" oder "compile" aussetzen. Die obige Deklaration enthält nur Substantive, keine Verben. Kompilieren und Testen sind Aufgaben, die von iwant implizit ausgeführt werden, um dem Benutzer die gewünschten Substantive zuzuweisen. Es ist nicht die Sprache. So benutzt du es.
"Java ist wortreich"
Ja, viel Java-Code ist ausführlich. Aber es ist nicht die Sprache, sondern die Art und Weise, wie Sie sie verwenden. Wenn eine Implementierung ausführlich ist, kapseln Sie sie einfach hinter einer netten Abstraktion. Viele GPLs bieten hierfür angemessene Mechanismen.
Stellen Sie sich das obige Java-Snippet vor, das in XML geschrieben ist. Ersetzen Sie Klammern durch spitze Klammern und verschieben Sie sie. Und dann duplizieren Sie jedes Keyword als Abschluss-Tag! Java als Syntax ist nicht ausführlich.
(Ich weiß, ein Vergleich mit XML ist, als würde man einem Baby Süßigkeiten abnehmen, aber so viele Builds werden zufällig in XML definiert.)
"Sie müssten Ihr Build-Skript kompilieren"
Dies ist ein gültiger Punkt. Trotzdem ist es nur ein kleines technisches Problem, das gelöst werden muss. Ich hätte es mit einer Bohnenschale oder einem anderen Interpreter lösen können . Stattdessen habe ich es gelöst, indem ich es als ein weiteres Build-Problem behandelt und mit einer einfachen Shell oder einem Ant-Skript gebootet habe, das einen einfachen Java-Bootstrapper kompiliert und ausführt.
"Java hat Boilerplate"
Wahr. Sie müssen Klassen importieren, Sie müssen "public", "class" und so weiter erwähnen. Und hier erzielen einfache externe DSLs einen anfänglichen leichten Gewinn.
Und wenn Ihr Projekt so trivial ist, dass dieses Boilerplate von Bedeutung ist, herzlichen Glückwunsch. Ihr Problem ist nicht schwierig und es spielt keine Rolle, wie Sie es lösen.
Viele Projekte erfordern jedoch viel mehr als die Erstellung, Berichterstattung und Verpackung. Wenn das Boilerplate von Java für Kundenprobleme akzeptabel ist, warum keine Probleme erstellen? Warum Schuhe nur für Kinder anderer machen?
quelle
Eine Sache, auf die sich die anderen Antworten meines Erachtens nicht bezogen haben, ist, dass die Einschränkungen und Transparenz dieser Build-Sprachen einen großen Teil dessen ausmachen, was sie nützlich macht. Nehmen wir zum Beispiel Maven. Ja, es führt Builds aus, definiert aber auch Abhängigkeiten. Dies ermöglicht es einem Maven-Build, diese Abhängigkeiten abzurufen und ihre Abhängigkeiten usw. zu betrachten.
Überlegen Sie, ob dies direkt mit Java geschehen ist. Das Build-Tool würde feststellen, dass eine Abhängigkeit besteht. Es müsste dann also eine andere Java-Anwendung herunterfahren und ausführen, um festzustellen, welche Abhängigkeiten es gibt. Aber für Maven werden einfach die Abhängigkeitserklärungen betrachtet. Die Maven-Build-Datei ist transparent. Eine vollständige Sprache von Turing ist von Natur aus nicht transparent und daher für einige Zwecke wie diesen unterlegen.
quelle