03.04.2019 | DaniD
Ein fundamentaler Grundsatz, der besonders in der Informatik gelebt wird. Bereits im Informatikstudium kommen Studierende mit diesem Paradigma als Bestandteil von „Clean Code“ in Programmiervorlesungen in Berührung.
In erster Instanz geht es hierbei darum, wiederkehrende Aufgaben in dedizierte Programmblöcke auszulagern und dann bei Bedarf aufzurufen – Stichwort Methoden und Funktionen. Schnell wird man aber erkennen, dass sich dieses Grundprinzip in weiteren Bereichen der Softwareentwicklung anwenden lassen sollte. Bestimmte Tätigkeiten wiederholen sich bei jedem neuen Software-Projektsetup. Dazu zählen beispielsweise das Einrichten eines Code-Repositorys, Erstellen einer Deployment-Pipeline und nicht zuletzt das Aufsetzen von Skeletons für Clients und Backend. Um einige dieser essentiellen Setupschritte nicht bei jedem neuen Projekt von Grund auf durchführen zu müssen, gibt es diverse Lösungsvarianten. Populär sind aktuell Coderepositories, die für viele Plattformen und Technologien vorkonfigurierten Boilerplate-Code bereitstellen, um einen schnellen Start mit den wertgenerierenden Aufgaben zu ermöglichen.
Nebst solchen Repositories haben sich auch eine Reihe von Code-Generatoren entwickelt, die repetitive Aufgaben abnehmen sollen. Oft wird bei der Verwendung dieser Generatoren zunächst ein Reihe von Fragen bezüglich der zu erstellenden Anwendung gestellt. Ja nach Antwort werden unterschiedliche Aspekte der neuen Applikation hinzugefügt oder weggelassen.
Eine populäre Konstellation im Webumfeld ist ein Spring Boot -Backend inklusive Datenbankanbindung, das via ReST-Schnittstellen mit einem WebClient, zum Beispiel Angular oder VueJS, kommuniziert. Eine Lösung die diese Zusammenstellung adressiert ist jHipster. Der FullStack-Generator wurde 2013 ins Leben gerufen und wird seither stetig weiterentwickelt und angepasst.
Die Erstellung einer jHipster-generierten Anwendung gestaltet sich als sehr unkompliziert. Dabei existieren mehrere Wege, um zur initialen Version zu kommen. Es besteht die Möglichkeit den jHipster-Generator als lokale Komponente zu installieren. Diese lässt sich über das Terminal beziehungsweise Kommandozeile bedienen. Nach dem Start des Generators wird anhand eines Fragenkatalog die gewünschte Konfiguration ermittelt. Die daraufhin erstellte Anwendung ist in der Regel sofort startbereit. Daneben besteht die Möglichkeit, den gleichen Fragenkatalog online auszufüllen und die Applikation komplett als ZIP-Archiv herunterzuladen. Daneben gibt es diverse andere Möglichkeiten für das initiale Projekt, wie als Docker Image und über diverse Packagemanager.
Im Rahmen einer Evaluation, welche Möglichkeiten sich zu schnellen Erstellung einer Applikationsgrundstruktur im Webumfeld eignen, haben wir uns jHipster genauer angesehen. Gewisse Punkte sind uns dabei aufgefallen. Meist positive, aber auch einige, mit denen wir etwas zu kämpfen hatten. Je nach Einsatz kann dies für den ein oder anderen aber weniger eine Hürde darstellen.
Wir haben uns hierfür für eine monolithische Anwendung mit Angular in der Version 6 entschieden.
Insgesamt haben wir es als sehr positiv empfunden, dass mehrere Wege zum jHipster-Skeleton angeboten werden. Über den lokal installierten Generator, als ZIP-Archiv über jHipster-Online oder Paketmanager.
Die lokale Installation des jHipster-Generator gestaltet sich teils etwas mühsam. Wir haben unsere Gehversuche mit jHipster auf einem frisch aufgesetzten MacBook unternommen. Um jHipster installieren zu können, musste zunächst homebrew und dann yarn installiert werden. Auf einer altgedienten Entwicklermaschine dürften diese Dependency-Manager in der Regel aber schon vorhanden sein, womit dieser Punkt nicht so sehr ins Gewicht fällt.
In der getesteten Version (5.8.1) beherrscht jHipster leider das Erzeugen von n:m-Beziehungen noch nicht. Diese Option steht weder beim Erzeugen der Entitäten mithilfe des Generators noch im erzeugten WebClient zur Verfügung. Blog- und StackOverflow-Einträge lassen aber darauf schliessen, dass an diesem Feature gearbeitet wird.
Um n:m-Beziehungen dennoch zu realisieren, bleibt daher aktuell nur der manuelle Eingriff. Dabei gilt es die Entitätsklasse mit einer entsprechenden JPA-Annotation zu versehen. Ausserdem muss das dazugehörige DTO und der entsprechende Mapper ergänzt werden. Auf Clientseite kann diese Art der Beziehung unterschiedlich abgebildet werden. Eine einfache Lösung ist die Verwendung eines Select-Elements, das eine Mehrfachauswahl unterstützt.
Wie eingangs erwähnt, wiederholen sich gewisse Aufgaben mit den Wachstum der Anwendung. Zum Beispiel werden mit dem Hinzufügen einer Entität in der Regel auch neue DTOs und Mapper zwischen DTO und Entitätenklasse geschrieben. Dies zieht normalerweise auch ein Datenbank-Update nach sich. Dies alles geschieht oft nach dem immergleichen Schema. Auf Clientseite gestaltet sich das gleiche Szenario.
Um dem Entwickler von diesen monotonen Prozessen weitestgehend zu entlasten, generiert jHipster alle notwendigen Bestandteile vom Backend bis zum Client. Ähnlich dem initialen Erstellen des Skeletons führt ein terminalbasierter Fragenkatalog durch den Generierungsprozess. Das Ergebnis ist eine JPA-annotierte Entity inklusive möglicher Constraints, ein DTO, eine Model-Mapperklasse und die Datenbankmigrationsbeschreibung via Liquibase. Auf Clientseite generiert jHipster eine eigene Komponente für die Entität, die das Template, Controller, Modell sowie Tests enthält.
Da Entitäten auch nachträglich via jHipster um Attribute ergänzt oder von diesen erleichtert werden können, wird clientseitig die betroffene Entität komplett neu generiert. Eventuell gemachte Änderungen an dieser Entität werden überschrieben. Für unseren Testfall hat es sich als Best Practise erwiesen, Komponenten, die nicht über jHipster generiert werden sollen, weil sie beispielsweise keiner Entität entsprechen oder nur anzeigenden Charakter haben, nicht in der logisch zugehörigen Komponente abzulegen. Stattdessen führten wir ein custom-Modul ein, in dem ebendiese Komponenten organisiert und registriert sind.
jHipster leistet sehr gute Arbeit für weit verbreitete Arten von Applikationen. Applikationen nämlich, die ihre Informationen in Entitäten ablegen und nach dem CRUD-Prinzip verwalten. Ja nach Architekturansatz sind diese Bedingungen für viele Anwendungen zutreffend. Für Webapplikationen mit statischem Inhalt ist eine vollständige jHipster-Anwendung aber zu schwergewichtig. Die Stärke von jHipster liegt also unter anderem auch darin, dem Entwickler so viel repetitive Arbeit wie möglich abzunehmen. Besonders bei der Generierung der üblichen CRUD-Methoden sowohl auf Client- als auch auf Serverseite macht sich dies deutlich bemerkbar.
Unserer Einschätzung und der entwickelten Applikation nach eignet sich der generierte Code durchaus auch für den produktiven Einsatz. Auch wenn jHipster besonders im Umfeld des “Rapid Prototypings” sich einen Namen gemacht hat. Viele Sicherheitsaspekte und Best Practises werden vom jHipster-Generator adressiert und angewandt. Selbstverständlich muss die erzeugte Anwendung aber noch an das jeweilige Produktionsumfeld angepasst werden, da der Fokus zunächst auf einer direkt lauffähigen und schnell erweiterbaren Applikation liegt, die das Entwicklungsteam möglichst rasch um wertvolle Businesscases ergänzen kann. Besonders in Bezug auf den erzeugten Webclient soll noch darauf hingewiesen werden, dass dieser lediglich ein Administrationswerkzeug für die zu verwaltenden Entitäten darstellt. Einen spezialisierten Client zu entwickeln, der die Bedürfnisse des Endbenutzers erfüllt, ist in der Regel die Aufgabe des Entwicklungsteams. Im besten Fall kann allerdings der Output des Generators für die Administrationsoberfläche auch für den Endbenutzer-Client verwendet werden.