Warum sollten Java-Entwickler Grails eine Chance geben?
Veröffentlicht: 2022-03-11Java verfügt über ein Ökosystem, das durch jahrelange Entwicklung gereift ist und sich als eine der zuverlässigsten Plattformen auf dem Markt etabliert hat. Es fehlen jedoch die notwendigen Mittel, um die Arbeit schnell zu erledigen, insbesondere bei Dingen wie Webanwendungen. Um Frustrationen mit dieser Art von Problemen zu vermeiden, entscheiden sich Entwickler oft stattdessen für Implementierungssprachen und ihre modernen Web-Frameworks wie Ruby mit Ruby on Rails, Python mit Django und so weiter. Im Gegensatz zu Java bieten diese einen viel einfacheren Weg zum Erstellen einer Webanwendung.
Glücklicherweise gibt es für Java-Entwickler, die Webanwendungen erstellen möchten, einen besseren Weg, und dieser beinhaltet Grails. In diesem Artikel werden wir sehen, wie Grails mit Groovy eine praktikable Alternative im JVM-Bereich ist. Wir werden uns einige Beispiele ansehen, bei denen Grails für uns als Java-Entwickler attraktiv ist und vielleicht jemand anderen dazu verleiten könnte, es ebenfalls zu versuchen.
Die Geschichte
In einem Startup, für das ich gearbeitet habe, hatten wir genau dieses Problem. Wir hatten eine Spring-Anwendung, mit der es immer schwieriger wurde, damit zu arbeiten. Da es immer größer wurde, stellten wir bald fest, dass das Umgestalten und Hinzufügen von Funktionen viel länger dauerte, als es sollte. Dies in Kombination mit einigen anderen Beweggründen veranlasste uns, unsere Kernanwendung neu zu schreiben. Wir waren auch offen dafür, bestehende Technologiestacks zu ändern oder zu ersetzen. Grails schien eine praktikable Wahl zu sein, da es in der JVM läuft und auf Technologien aufbaut, die wir bereits kannten. Es verwendet die Programmiersprache Groovy, erlaubt Ihnen aber gleichzeitig, sie mit Java zu mischen. Also haben wir den Sprung gewagt.
Vollgas voraus
Eine Sache, in der sich Grails wirklich auszeichnet, ist es, den Start eines neuen Projekts einfach zu machen. Es ist so einfach wie das Ausführen eines Befehls, der die Projektstruktur mit allen Ordnern erstellt, die für die später hinzuzufügenden Klassen benötigt werden. Das Hinzufügen von Modellklassen, Controllern, Diensten und Webseiten erfordert einen ähnlich geringen Aufwand. Das einzige, worauf Sie achten müssen, ist die richtige Benennung und Platzierung der Dinge. Im Gegensatz zu Java gibt es praktisch keinen Boilerplate-Code, der da sein muss, nur weil er da sein muss. Dies wird teilweise durch die Verwendung von Spring und Hibernate ermöglicht, die zwei der Säulen von Grails sind, sowie durch das Konzept der Codierung nach Konvention. Um das Projekt auszuführen, wird Grails mit Apache Tomcat als Entwicklungsserver geliefert. Alles, was wir tun müssen, ist, das Projekt in unserer IDE auszuführen, und der Server wird mit unserem bereitgestellten Code gestartet. Außerdem übernimmt das Object Relational Mapping (GORM) von Grails mit Hibernate die Erstellung der Datenbank für uns. Um eine vorhandene Datenbank zu verwenden, müssen wir die JDBC-Verbindungseigenschaften konfigurieren oder es einfach standardmäßig belassen, um eine In-Memory-Instanz zu verwenden. Sobald der Server mit Grails läuft (benötigt etwas mehr als eine Spring MVC-Anwendung), können wir den Code ändern und die Hot-Deploy-Funktion hält unsere Debug-Sitzung mit der neuesten Version ausgestattet. Die einzigen Klassen, die auf diese Weise nicht neu geladen werden können, sind die Entitätsklassen.
Das Auffüllen der Datenbank kann mithilfe von SQL-Skripten erfolgen, aber das kann mühsam werden. Alle Grails-Projekte enthalten eine Bootstrap-Klasse, die ausgeführt wird, wenn unsere Anwendung ausgeführt wird. In dieser Klasse können wir Daten speichern oder ändern und so unseren Anwendungszustand initialisieren. Dies hat sich für uns als sehr nützlich erwiesen, sodass wir sofort einige Testfälle in der Entwicklungsversion haben.
Manipulation von Daten
Eines der Dinge, die uns bei Grails sofort aufgefallen sind, war die einfache Arbeit mit Daten. Das Lesen aus der Datenbank ist eine Aufgabe, die immer wieder ausgeführt werden muss. Und oft ist es einfach. Wie das Abrufen einer oder mehrerer Entitäten, die bestimmte Kriterien erfüllen, und das anschließende Aggregieren. Warum nicht einen dynamischen Finder dafür verwenden? Es ist eine Möglichkeit, Daten abzufragen, bei der Methoden zur Laufzeit dynamisch erstellt werden. Sie müssen lediglich einer Namenskonvention folgen.
def users = User.findAllByLastNameLikeOrAgeGreaterThan('Doe%', 30)
Die Zeile über der Zeile ruft alle Benutzerobjekte ab, deren Nachname mit „Doe“ beginnt oder älter als 30 Jahre ist. Ja, kein sehr anspruchsvoller Fall, aber Sie verstehen das Wesentliche.
Was wäre, wenn wir diese Liste zusätzlich nach denen filtern wollten, deren Eigenschaft „failedLogins“ größer als 10 ist? Und was wäre, wenn wir sie nach ihrem Erstellungsdatum sortieren wollten? Und was wäre, wenn wir ihre Vornamen verketten oder das maximale Alter der zurückgegebenen Benutzer ermitteln wollten?
users = users.findAll() { it.failedLogins > 10 } users = users.sort { it.dateCreated } def firstNamesString = users.firstName.join(', ') def maximumAge = users.age.max()
Die obigen Beispiele mögen einfach aussehen, aber sie zeigen, wie leistungsfähig Grails zum Abfragen, Filtern und Manipulieren von Daten sein kann. In Java 8 können Sie für einige dieser Fälle ähnliche Ergebnisse erzielen, aber es erfordert immer noch mehr Code als Grails.
Manchmal möchte ich anders gestalten
Ein dynamischer Konstruktor oder benannter Argumentkonstruktor ist eine Funktion, die viele von uns in Java haben wollten. Es ist schön zu definieren, welche Konstruktoren eine bestimmte Klasse zulässt, aber in vielen Fällen möchten Sie nur einige Eigenschaften festlegen und die verdammte Instanz erhalten. Groovy fügt für jede Entität einen speziellen Konstruktor hinzu, der im Grunde die Eleganz einer Karte als Eingabe nimmt und die Eigenschaften mit den Karteneinträgen setzt.
def Person = new Person(name: 'Batman', age: 57)
Dieser Ansatz führt zu Code, der viel ausdrucksstärker ist und den gesamten Konstruktor-Boilerplate-Code überflüssig macht.
Und übrigens, hier sind einige Beispiele für die Großartigkeit und Eleganz von Groovys Karten:
def emptyMap = [:] def map = [bread:3, milk:5, butter:2] map['bread'] = 4 map.milk = 6
Dies ist ein weiteres Beispiel dafür, wie der Code kurz und einfach, aber dennoch leistungsstark sein kann. Es zeigt, wie die Inline-Initialisierung verwendet werden kann und wie Kartenwerte ähnlich wie Objekteigenschaften manipuliert werden können. Es ist nicht erforderlich, traditionelle Java-Methoden für grundlegende Manipulationen aufzurufen, es sei denn, Sie möchten dies wirklich.
Wir brauchen mehr Kraft!
Natürlich gibt es kein Framework, das alles kann, aber wenn wir die Lücken füllen, sollten wir sehen, was möglicherweise bereits verfügbar ist, bevor wir versuchen, unsere eigene Lösung zu implementieren. Um unser Arsenal an Grails-basierten Funktionen zu erweitern, können wir Grails-Plugins verwenden. Die Installation eines Plugins erfolgt einfach durch Hinzufügen einer weiteren Zeile in der BuildConfig
-Klasse, die in jedem Grails-Projekt vorhanden ist (Code-Konvention schlägt wieder zu!).

compile ':spring-security-core:2.0-RC4'
Die obige Zeile fügt unserer Anwendung den Spring-Sicherheitskern hinzu, und es ist praktisch keine weitere Konfiguration erforderlich, um diese Funktionalität zu integrieren.
Lassen Sie mich Ihnen von einem Fall erzählen, mit dem wir uns befassen mussten. Wir mussten eine Suche implementieren, die sich über mehrere Datenentitäten erstreckt. Grails hat ein Elasticsearch-Plugin, das einfach zu verwenden ist. Wie bereits erwähnt, müssen wir nur das Plugin in der Konfigurationsdatei referenzieren und schon kann es losgehen. Wenn wir nach Entitäten einer bestimmten Klasse suchen möchten, müssen wir dieser Klasse nur eine statische „durchsuchbare“ Eigenschaft hinzufügen. Und wenn wir wollen, können wir sogar die Objekte einschränken, die durchsucht werden dürfen.
class User { static searchable = { only = name } String name Double salary }
Es ist so wenig Code, aber unter der Haube indizieren Grails und das Elasticsearch-Plugin automatisch alle Benutzer nach Namen und ermöglichen uns die Suche nach Namen. Auch der eigentliche Suchaufruf ist sehr prägnant:
User.search("${params.query}")
Wenn wir nicht wollen, müssen wir den Lucene-Index nie anfassen. Alles wird automatisch für uns erledigt. Das Plugin verfügt sogar über eine API zum Anzeigen von Suchergebnissen – es kann die im gesuchten Text gefundene Übereinstimmung hervorheben. Dies ist nur ein Beispiel dafür, wie ein Plugin ein riesiges Bündel von Funktionen bereitstellen kann, die uns viel effizienter machen können, da wir es nicht selbst implementieren müssen.
Wir brauchen noch mehr Power
Plugins sind großartig, aber manchmal brauchen wir kein ganzes Plugin, wir wollen nur etwas mehr. Erinnern Sie sich an das letzte Mal, als Sie eine zusätzliche Methode für eine vorhandene Java-Klasse haben wollten, diese aber nicht erweitern/überschreiben wollten (oder konnten)? In Groovy können Sie Methoden und Eigenschaften zu bestehenden Klassen oder sogar nur zu bestimmten Instanzen davon hinzufügen. Beispielsweise können Sie der java.util.Date
-Klasse eine formatting
hinzufügen, was großartig ist, wenn Sie Datumsangaben konsistent formatieren und einfach keine statischen util-Klassen schreiben oder verschiedene Filter definieren möchten.
Date.metaClass.formatDate = { delegate.format("dd.MM.yyyy") }
Was ist, wenn Sie eine Liste von Benutzern nach einem berechneten Wert sortieren möchten und dies nur in einem Fall benötigen (dh das Hinzufügen einer neuen Methode in der Benutzerklasse wäre verschmutzend)? Sie könnten jeder dieser Instanzen eine Eigenschaft hinzufügen und die Sammlung dann einfach nach dieser Eigenschaft sortieren oder filtern:
user.metaClass.computedProp = 312 * 32 * 3
Groovy-Autoren haben bereits viele Verbesserungen zu einigen der Java-Kernklassen hinzugefügt, sodass wir dies nicht tun müssen. Nachfolgend finden Sie einige Beispiele.
Verwenden von „Minus“, um alle Elemente aus einer Sammlung zu entfernen, die in einer anderen Sammlung vorhanden sind.
assert [1, 2, 3, 4, 4, 5] - [2, 4] == [1, 3, 5]
Zusätzliche Methoden zum Bearbeiten von java.util.Date
Objekten, die so oft nützlich sind, wie z. B. das Hinzufügen/Subtrahieren von Tagen von Datumsangaben oder das Abrufen/Einstellen eines bestimmten Datumsfelds, ohne es in den Calendar
zu konvertieren oder zusätzliche Bibliotheken zu verwenden.
def yesterdayAllMyTroublesSeemedSoFarAway = new Date() - 1 def myAwesomeAnniversaryYear = myAwesomeDate[Calendar.YEAR] + 1 myAwesomeDate.set(year: myAwesomeAnniversaryYear, second: 0)
Wenn Sie mit der Datumsmanipulation wirklich beschreibend werden wollen, können Sie einfach die von Groovy hinzugefügte TimeCategory
-Klasse verwenden:
use (TimeCategory) { println 1.minute.from.now println 10.hours.ago def someDate = new Date() println someDate - 3.months }
Ein Hammer und ein Nagel
Dann gibt es die IDEs. Eclipse-basiertes GGTS und IntelliJ IDEA sind für die Arbeit mit Grails eingerichtet. Sie verstehen die Projektstruktur (und helfen Ihnen beim Navigieren durch Ordner und Ressourcen) und haben Verknüpfungen für die Befehle, die Sie am häufigsten verwenden werden (z. B. Controller hinzufügen, Seite hinzufügen, Projekt ausführen usw.). Mit Grails führen Sie Befehle aus (um ein Projekt auszuführen oder eine neue Plugin-Funktionalität einzurichten) und Sie benötigen verschiedene Konfigurationen, die auch von den IDEs abgedeckt werden. Die Codevervollständigung funktioniert gut in Grails-Webvorlagenseiten, auf denen Sie häufig auf Controller und Aktionen verweisen. Es gibt auch andere IDEs, die mit Grails verwendet werden können, wie Netbeans, TextMate, Emacs und andere.
Was ist mit der dunklen Seite?
Wie bei allem im Leben gibt es auch bei Grails Vorbehalte. Unter der Haube wird viel gezaubert, was oft eine gute Sache sein kann, aber manchmal wird das Ergebnis nicht das sein, was Sie erwartet haben. Fehler treten auf, nur weil man nicht tippt (ja, Typen sind in Groovy optional) und nicht vorsichtig genug ist. Und vielleicht bemerken Sie einen Fehler erst, wenn es zu spät ist. Außerdem ist es sehr verlockend, Einzeiler zu schreiben, um Ihre Kollegen zu beeindrucken. Und du selbst. Aber diese leistungsstarken Codezeilen sind für Ihre Kollegen möglicherweise nicht so selbsterklärend. Oder sogar für sich selbst in ein paar Monaten. Deshalb denke ich, dass Grails mehr Programmierdisziplin erfordert als einige der traditionelleren Frameworks.
Zeit ist Geld
Die Codierung sollte nicht länger dauern, nur weil Ihr aktuelles Framework dies erfordert. Gerade bei der immer größer werdenden Zahl an Startups ist es heutzutage wichtig, sich auf die wirklich wichtigen Aufgaben zu konzentrieren und so effizient wie möglich zu sein. Zeit ist in der Tat Geld und die Markteinführungszeit ist entscheidend. Sie müssen in der Lage sein, schnell zu handeln und die Lösung zu implementieren, bevor die Zeit abläuft und Ihre Konkurrenz Ihnen zuvorkommt.
Meine Freunde, die mit Ruby on Rails oder Python/Django arbeiten, sagen mir schon lange, wie cool diese Technologien sind. Und es fühlte sich wirklich albern an, daran zu denken, wie viel mehr Zeit ich in Java gebraucht habe, um Code zu schreiben, der etwas in einer Datenbank speichert und es auf einer Webseite anzeigt. Grale können in der Tat eine nützliche Antwort sein. Es ist nicht so, dass Sie dies nicht mit reinem Java, Spring MVC und Hibernate tun könnten. Sie könnten. Vielleicht läuft Ihre Anwendung sogar etwas schneller. Aber mit Grails erledigen Sie die Arbeit schneller.