PDF ist vermutlich das wichtigste interoperable Dokumentenformat zwischen Betriebssystemen und Geräten wie Computer, Smartphone und Tablet. Die wichtigste Eigenschaft für PDF ist die Unveränderlichkeit der Dokumente. Natürlich sind auch hier Grenzen gesetzt und man kann heutzutage problemlos mit entsprechenden Programmen Seiten aus einem PDF Dokument entfernen oder hinzufügen. Dennoch lassen sich die Inhalte der einzelnen Seiten nicht ohne Weiteres verändern. Wo vor Jahren noch kostspielige Spezialsoftware wie beispielsweise Acrobat von Adobe nötig war, um mit PDF umzugehen, sind mittlerweile viele kostenfreie Lösungen auch für den kommerziellen Einsatz verfügbar. So beherrschen die gängigen Office Suiten den Export des Dokumentes als PDF.
Gerade im Geschäftsbereich ist PDF eine hervorragende Wahl, um Rechnungen oder Berichte zu generieren. Hier setzt auch dieser Artikel an. Ich beschreibe, wie einfache PDF Dokumente für die Rechnungslegung etc. genutzt werden können. Komplizierte Layouts, wie sie beispielsweise für Magazine und Zeitschriften in Verwendung kommen, sind nicht Teil dieses Artikels.
Technisch kommt die frei verfügbare Bibliothek openPDF zum Einsatz. Das Konzept ist, aus einem gültigen HTML Code, welcher in einem Template enthalten ist, eine PDF zu generieren. Da wir uns im JAVA Umfeld bewegen, ist die Template Engine der Wahl Velocity. Alle diese Abhängigkeiten nutzt TP-CORE in der Funktionalität PdfRenderer, welche als Fassade implementiert ist. Dies soll die Komplexität der PDF-Generierung in der Funktionalität kapseln und einen Austausch der Bibliothek ermöglichen.
Auch wenn ich nun kein Spezialist der PDF-Generierung bin, habe ich im Laufe der Jahre einige Erfahrungen speziell mit dieser Funktionalität in Bezug auf die Wartbarkeit von Softwareprojekten sammeln können. Dazu gibt es sogar einen Konferenzvortrag. Als ich vor sehr vielen Jahren den Entschluss gefasst hatte, PDF in TP-CORE zu unterstützen, gab es nur die iText-Bibliothek, die zu dieser Zeit mit der Version 5 frei verfügbar war. Ähnlich wie Linus Torvalds mit seinem ursprünglich genutzten Source Control-Management-System, erging es mir. Itext wurde kommerziell und ich brauchte eine neue Lösung. Nun, ich bin nicht Linus, der mal fix GIT aus dem Boden stampft, also habe ich nach einiger Wartezeit openPDF entdeckt. OpenPDF ist ein Fork von iText5. Jetzt musste ich meinen bestehenden Code entsprechend anpassen. Das erforderte einiges an Zeit, war aber dank meiner Kapselung eine überschaubare Aufgabe. In diesem Anpassungsprozess habe ich allerdings Probleme entdeckt, die mir in meiner kleinen Welt bereits das Leben schwer gemacht haben, also habe ich TP-CORE Version 3.0 veröffentlicht, um in der Funktionalität Stabilität zu erreichen. Wer also TP-CORE in einer 2.X Version verwendet, findet dort als PDF Lösung noch iText5. Das soll aber jetzt genug über die Entstehungsgeschichte sein. Kümmern wir uns darum, wie wir aktuell mit TP-CORE 3.1 PDF generieren können. Auch hier gilt: Mein größtes Ziel ist es, eine möglichst hohe Kompatibilität zu erreichen.
Bevor wir beginnen können, müssen wir TP-CORE als Abhängigkeit in unser Java Projekt einbinden. Das Beispiel demonstriert die Verwendung von Maven als Build Werkzeug, kann aber leicht auf Gradle umgestellt werden.
Um etwa eine Rechnung zu generieren, brauchen wir verschiedene Schritte. Zu erst benötigen wir ein HTML Template, das wir mit Velocity erzeugen. Das Template kann natürlich Platzhalter für Namen und Adresse enthalten, wodurch Serienbriefe und Batchverarbeitung möglich sind. Der folgende Code zeigt, wie wir damit umgehen können.
<h1>HTML to PDF Velocity Template</h1><p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.</p><p>Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.</p><h2>Lists</h2><ul><li><b>bold</b></li><li><i>italic</i></li><li><u>underline</u></li></ul><ol><li>Item</li><li>Item</li></ol><h2>Table 100%</h2><tableborder="1"style="width: 100%; border: 1px solid black;"><tr><td>Property 1</td><td>$prop_01</td><td>Lorem ipsum dolor sit amet,</td></tr><tr><td>Property 2</td><td>$prop_02</td><td>Lorem ipsum dolor sit amet,</td></tr><tr><td>Property 3</td><td>$prop_03</td><td>Lorem ipsum dolor sit amet,</td></tr></table><imgsrc="path/to/myImage.png"/><h2>Links</h2><p>here we try a simple <ahref="https://together-platform.org/tp-core/">link</a></p>
template.vm
In dem Template sind drei Properties enthalten: $prop_01, $prop_02 und $prop_03, die wir mit Werten füllen müssen. Das gelingt uns mit einer einfachen HashMap, die wir mit dem TemplateRenderer einfügen, wie das folgende Beispiel zeigt.
directory – Der vollständige Pfad vo das Template zu finden ist.
template – den Namen des Velocity-Templates
properties – Die HashMap mit den zu ersetzenden Variablen
Das Ergebnis ist ein gültiger HTML Code, aus dem wir nun über den PdfRenderer das PDF generieren können. Eine Besonderheit ist die Konstante SYSTEM_USER_HOME_DIR, welche auf das Nutzerverzeichnis des aktuell angemeldeten Benutzers zeigt und die Unterschiede einzelner Betriebssysteme wie Linux und Windows abfängt.
PdfRendererpdf=newOpenPdfRenderer();pdf.setTitle("Title of my own PDF");pdf.setAuthor("Elmar Dott");pdf.setSubject("A little description about the PDF document.");pdf.setKeywords("pdf, html, openPDF");pdf.renderDocumentFromHtml(directory +"myOwn.pdf", htmlTemplate);
Das Listing zum Erstellen der PDF ist überschaubar und recht selbsterklärend. Es ist natürlich möglich, das HTML hardcodiert zu übergeben. Die Nutzung des Templates erlaubt hier eine Trennung von Code und Design, was auch spätere Anpassungen flexibel erlaubt.
Das Standardformat ist A4 mit den Dimensionen size: 21cm 29.7cm; margin: 20mm 20mm; und ist als inline CSS definiert. Über die Methode setFormat(String format); lässt sich dieser Wert individuell festlegen. Der erste Wert steht hierbei für die Breite und der zweite Wert für die Höhe.
Der PDF Renderer hat auch die Möglichkeit, einzelne Seiten aus einem Dokument zu löschen.
Wir sehen also, dass bei der Implementierung der PDF Funktionalität sehr viel Wert auf eine einfache Handhabung gelegt wurde. Dennoch gibt es viele Möglichkeiten, individuelle PDF Dokumente zu erstellen. Daher hat die Lösung, über HTML das Layout zu definieren, einen besonderen Reiz. Trotz, dass der PdfRenderer mit einer sehr überschaubaren Funktionalität aufwartet, ist es sehr einfach möglich, durch den Vererbungsmechanismus von Java das Interface und die zugehörige Implementierung durch eigene Lösungen zu erweitern. Diese Möglichkeit besteht auch für alle anderen Implementierungen aus TP-CORE.
TP-CORE ist auch für den kommerziellen Gebrauch frei und hat dank der Apache 2 Lizenz keine Einschränkungen. Der Source Code ist unter https://git.elmar-dott.com zu finden und die Dokumentation inklusive Security und Testcoverage findet sich unter https://together-platform.org/tp-core/.
Ein alter Handwerksmeister pflegte immer zu sagen: Wer schreibt, der bleibt. Seine Intention war vor allem, ein vernünftiges Aufmaß und Wochenberichte seiner Gesellen zu bekommen. Diese Informationen benötigte er, um eine korrekte Rechnung stellen zu können, was für den Erfolg des Unternehmens maßgeblich war. Dieses Bild lässt sich auch gut auf die Softwareentwicklung übertragen. Erst als die in Japan von Yukihiro Matsumoto entwickelte Programmiersprache Ruby eine englischsprachige Dokumentation besaß, begann der weltweite Siegeszug von Ruby.
Wir sehen also, dass Dokumentation einen durchaus hohen Stellenwert für den Erfolg eines Softwareprojektes haben kann. Es beschränkt sich nicht nur auf einen Informationsspeicher im Projekt, wo neue Kollegen notwendige Details erfahren. Natürlich ist für Entwickler Dokumentation ein recht leidiges Thema. Stetig muss diese aktuell gehalten werden und oft fehlen auch Fertigkeiten, um die eigenen Gedanken sortiert und nachvollziehbar für andere auf Papier zu bringen.
Ich selbst kam vor sehr vielen Jahren erstmalig mit dem Thema Dokumentation durch das Lesen des Buches „Softwaretechnik“ von Johannes Siedersleben in Berührung. Dort wurde Ed Yourdon mit der Aussage zitiert, dass vor Methoden wie UML die Dokumentation oft in der Form einer viktorianischen Novelle vorlag. Während meines Berufslebens habe ich auch einige solcher viktorianischen Novellen angetroffen. Das Ärgerliche daran war: Nachdem man sich durch die Textwüste gekämpft hatte – anders als mit Überwindung und Kampf kann man das Gefühl nicht beschreiben –, hatte man die gesuchten Informationen immer noch nicht. Frei nach Goethes Faust: „So steh ich da ich armer Tor und bin so klug als wie zuvor.“
Hier sehen wir bereits einen ersten Kritikpunkt für schlechte Dokumentationen: eine unangemessene Länge der Ausführungen, die wenig Informationen enthalten. Hier müssen wir uns der Tatsache bewusst werden, dass das Schreiben nicht jedem in die Wiege gelegt wurde. Schließlich ist man ja Softwareentwickler und nicht Buchautor geworden. Das bedeutet für das Konzept „erfolgreiche Dokumentation“, dass man möglichst niemanden zu seinem Glück zwingen sollte und sich besser im Team nach Personen umschaut, die für Dokumentation ein Händchen haben. Das soll nun aber nicht bedeuten, dass alle anderen von der Aufgabe Dokumentation freigestellt sind. Ihr Input ist für die Qualität essenziell. Korrekturlesen, auf Fehler hinweisen und Ergänzungen vorschlagen sind durchaus notwendige Punkte, die sich gut auf vielen Schultern verteilen lassen.
Es ist durchaus ratsam, das Team, oder einzelne Teammitglieder gelegentlich rhetorisch zu schulen. Dabei sollte der Fokus auf einer präzisen, kompakten und verständlichen Ausdrucksweise liegen. Dabei geht es auch darum, die eigenen Gedanken so zu sortieren, dass diese auf Papier gebracht werden können und dabei einem roten Faden folgen. Die dadurch verbesserte Kommunikation wirkt sich sehr positiv auf die Entwicklungsprojekte aus.
Eine aktuell gehaltene Dokumentation, die gut zu lesen ist und wichtige Informationen enthält, wird schnell zu einem lebenden Dokument, ganz gleich, welche Formen gewählt wurden. Dies ist auch ein grundlegendes Konzept für erfolgreiches DevOps und agile Vorgehensmodelle. Denn diese Paradigmen setzen auf einen guten Informationsaustausch und adressieren auch das Vermeiden von sogenannten Informationssilos.
Ein Punkt, der mich wirklich triggert, ist die Aussage: Unsere Tests sind die Dokumentation. Nicht alle Stakeholder können programmieren und sind daher auch nicht in der Lage, die Testfälle zu verstehen. Zudem demonstrieren Tests zwar das Verhalten von Funktionen, sie demonstrieren aber nicht per se die richtige Verwendung. Meist fehlen auch Variationen von verwendbaren Lösungen. Damit Testfälle einen dokumentativen Charakter haben, ist es notwendig, spezielle Tests exakt für diesen Zweck zu entwickeln. Dieses Vorgehen hat meiner Ansicht nach zwei gravierende Vorteile. Zum Ersten bleibt die Dokumentation zur Implementierung aktuell, denn bei Änderungen schlägt der Testfall fehl. Ein weiterer positiver Effekt ist, dass der Entwickler über die Verwendung seiner Implementierung bewusst wird und einen ungünstigen Entwurf zeitnah korrigieren kann.
Natürlich gibt es mittlerweile unzählige technische Lösungen, die je nach Sichtweise auf das System für unterschiedliche Personengruppen geeignet sind. Issue- und Bug-Tracking Systeme wie beispielsweise das kommerzielle JIRA oder das freie Redmine bilden ganze Prozesse ab. Sie erlauben es den Testern, erkannte Probleme und Fehler der Software einer Releaseversion zuzuordnen. Projektleiter können mit dem Release Management eine Priorisierung der Korrekturen vornehmen und die Entwickler dokumentieren die verwendete Korrektur. Soweit die Theorie. In der Praxis habe ich in nahezu jedem Projekt erlebt, wie in diesen Systemen die Kommentarfunktion als Chat missbraucht wurde, um den Änderungsstatus zu beschreiben. Als Ergebnis hat man eine Fehlerbeschreibung mit unzähligen nutzlosen Kommentaren und wirkliche weiterführende Informationen fehlen komplett.
Eine weitverbreitete technische Lösung in Entwicklungsprojekten sind auch sogenannte Enterprise Wikis. Sie ergänzen einfache Wikis durch eine Navigation und ermöglichen das Erstellen geschlossener Spaces, auf die nur explizit zugelassene Nutzergruppen feingranulare Berechtigungen wie Lesen oder Schreiben erhalten. Neben der weitverbreiteten kommerziellen Lösung Confluence gibt es auch eine freie Variante namens Blue Spice, die auf dem MediaWiki basiert. Wikis erlauben die kollaborative Arbeit an einem Dokument und die einzelnen Seiten können auch über verschiedene Zusammenstellungen als PDF exportiert werden. Damit die Wikiseiten auch benutzbar bleiben, sollte man Wert auf eine saubere und möglichst einheitliche Formatierung legen. Tabellen sollten mit ihrem Inhalt auf eine A4 Seite passen, ohne dass es zu unerwünschten Umbrüchen kommt. Das verbessert den Lesefluss. Es gibt auch viele Fälle, in denen Aufzählungen der Übersichtshalber Tabellen vorzuziehen sind.
Dies bringt uns auch zu einem weiteren sehr heiklen Thema, den Grafiken. Es ist durchaus korrekt, dass ein Bild oft mehr als tausend Worte sagt. Aber eben nicht immer! Im Umgang mit Grafiken ist es wichtig, sich bewusst zu sein, dass Bilder oft einiges an Zeit für die Erstellung benötigen und oft auch nur mit viel Aufwand angepasst werden können. Daraus ergeben sich einige Konsequenzen, um sich das Leben zu erleichtern. Zum Erstellen von Grafiken wird sich auf ein Standardprogramm (Format) festgelegt. Auf teure Grafikprogramme wie Photoshop und Corel ist zu verzichten. Grafiken, die für Wikiseiten erstellt wurden, sind in ihrem Original, also der änderbaren Datei, an die Wikiseite anzufügen. Es kann auch ein eigenes Repository dafür aufgebaut werden, um so eine Wiederverwendung in anderen Projekten zu ermöglichen.
Wenn ein Bild keinen Mehrwert bedeutet, sollte man darauf besser verzichten. Dazu ein kleines Beispiel. Es ist nicht notwendig, eine Grafik anzufertigen, auf der 10 Strichmännchen abgebildet sind, unter denen dann der Rollenname oder eine Person steht. Hier ist es zielführend, eine einfache Aufzählung anzufertigen, die sich im Übrigen auch leichter ergänzen beziehungsweise anpassen lässt.
Aber auch auf überfrachtete Grafiken sollte man verzichten. Treu nach dem Motto „Viel hilft viel“: Sorgen zu detaillierte Informationen eher für Verwirrung und können zu Missinterpretationen führen. Eine Buchempfehlung ist „Softwarearchitekturen dokumentieren und kommunizieren“ von Stefan Zörner. Er arbeite in diesem Titel optimal heraus, wie wichtig die verschiedenen Sichtweisen auf ein System sind und welche Personengruppen mit einer expliziten Sicht angesprochen werden. Dazu möchte ich auch die Gelegenheit nutzen, um seine 7. Regeln für eine gute Dokumentation wiederzugeben.
Schreibe aus Sicht des Lesers.
Vermeide unnötige Wiederholungen.
Vermeide Mehrdeutigkeiten, wenn nötig Notation erläutern.
Verwende Standards wie z. B. UML.
Halte Begründungen (Warum) fest.
Die Dokumentation ist aktuell zu halten, aber nie zu aktuell.
Überprüfe die Gebrauchstauglichkeit (Review).
Wer im Projekt damit beauftragt ist, die Dokumentation zu schreiben beziehungsweise deren Fortschritt und Aktualität sicherzustellen hat, sollte sich immer bewusst sein, dass wichtige Informationen enthalten sind, diese auch korrekt und verständlich dargestellt werden. Eine kompakte und übersichtliche Dokumentation lässt sich auch bei fortschreitendem Projekt problemlos anpassen und erweitern. Anpassungen gelingen immer dann am besten, wenn der betroffene Bereich möglichst zusammenhängend ist und möglichst nur einmal vorkommt. Diese Zentralisierung erreicht man durch Referenzen und Verlinkungen, so dass die Änderung im Original sich auf die Referenzen auswirkt.
Natürlich gibt es zum Thema Dokumentation noch viel mehr zu sagen, schließlich ist es Gegenstand verschiedener Bücher, aber das würde den Rahmen dieses Artikels übersteigen. Mir ging es vor allem darum, für das Thema eine Sensibilisierung zu schaffen, denn Paradigmen wie Agilität und DevOps basieren auf einem guten Informationsfluss.
Nachdem wir im ersten Teil dieses Workshops eher allgemein Fragestellungen wie Dateisysteme und Partitionen besprochen haben, wenden wir uns im zweiten und letzten Teil der Artikelserie verschiedenen Diagnosetechniken zu. Unser Hauptarbeitsgerät hierfür wird die Bash sein, da die folgenden Werkzeuge alle kommandzeilenbasiert sind.
Auch für diesen Teil gilt, größte Sorgfalt walten zu lassen. Die hier beschriebenen Praktiken können bei unsachgemäßer Anwendung zu Datenverlusten führen. Für etwaige Schäden übernehme ich keine Haftung.
Beginnen wir auch gleich mit der Möglichkeit, herauszufinden, wie viel Speicher wir noch auf unserer Festplatte freihaben. Wer gelegentlich auf Servern sein Unwesen treibt, kommt um den Befehl df nicht umher. Schließlich hat der SSH Client kein grafisches Interface und man muss sich auf der Shell zurechtfinden.
Mit df -hT lassen sich alle Speicher, physisch und virtuell, in menschenlesbarer Form anzeigen.
Wie wir in der Ausgabe sehen können, ist der Mountpunkt / ein ext4 Dateisystem, mit einer nvme SSD die eine Kapazität von 1,8 TB hat, von der circa 1,2 TB noch frei sind. Würden noch andere Speichermedien wie externe Festplatten oder USB vorhanden sein, wären sie ebenfalls Bestandteil der Liste. Sicher gehört etwas Übung dazu, den Blick für die relevanten Details zu schärfen. Im nächsten Schritt wollen wir uns ein wenig in der Diagnose üben.
lsblk
Falls die Ausgabe von df zu unübersichtlich ist, kann auch auf das Werkzeug lsblk zurückgegriffen werden, das für Anfänger eine etwas verständlichere Auflistung bereitstellt.
Um gleich vor der Benutzung unseren neu erstandenen Speicher auf Herz und Nieren zu prüfen, bedienen wir uns der sogenannten S.M.A.R.T (Self-Monitoring, Analysis and Reporting Technology) Tools. Das kann man zum einen mit dem im ersten Teil dieses Artikels vorgestellten Programm Disks tun, oder mit ausführlicheren Informationen über die Bash. Mit df -hT haben wir die SSD /dev/nvme0 bereits identifiziert, sodass wir smartctl aufrufen können.
Eine sehr praktische Informationsquelle, besonders wenn man beabsichtigt, eine gebrauchte Platte zu verbauen. Glücklicherweise zeigt meine System SSD nach knapp zwei Jahren Nutzung keine Auffälligkeiten.
fdisk
Der Klassiker unter den Festplattenprogrammen ist fdisk, das auch unter Windows Systemen verfügbar ist. Mit fdisk können nicht nur Platten formatiert werden, sondern auch einige Informationen herausgekitzelt werden. Hierfür gibt es die Parameter -l für list und -x mit mehr Details. Das Programm fdisk ist recht komplex und zum Formatieren von Datenträgern empfehle ich eher die im ersten Teil dieses Artikels vorgestellten grafischen Varianten Disks und Gparted. Mit dem grafischen Interface ist die Wahrscheinlichkeit, Fehler zu machen, weitaus geringer als in der Shell.
Sollten wider Erwarten Probleme auftauchen, besteht mit dem Werkzeug fsck (File System Consistency Check) die Möglichkeit, das Dateisystem zu überprüfen und gegebenenfalls zu reparieren. Dazu muss man allerdings die entsprechende Partition angeben.
sudo fsck /dev/sdc
Wie man in dem Screenshot sehen kann, hatte ich vor einiger Zeit eine Partition mit einem defekten Superblock, sodass ein Zugriff auf die Daten nicht mehr möglich war. Grund für den Fehler war eine kaputte Speicherzelle in der SSD. Mit etwas Mühe ließ sich dann auf die Daten zugreifen und ich konnte diese auf einen anderen Speicher kopieren. Das klappt nicht immer. Weshalb ich als kleinen Ratschlag mitgeben möchte, vor solchen Rettungsaktionen immer gut vorbereitet zu sein. Das heißt, auch ein entsprechend großes, funktionierendes Ziellaufwerk bereit zu haben, um bei Erfolg sofort eine Sicherungskopie anfertigen zu können. Viele der hier vorgestellten Operationen verändern die Daten auf dem Speicher und es ist nicht sicher, ob ein erneuter Zugriff gelingen wird.
Linux Sysadmin Witz
Linux Sys-Admins empfehlen Anfängern gern das Löschen der französischen Sprachdateien, die man ja nicht braucht, um Platz zu sparen. Dazu soll man den Befehl sudo rm -fr / in der Konsole eintippen und ENTER drücken. Das sollte man auf keinen Fall tun, denn der Befehl löscht die gesamte Festplatte. Es gilt als das Gefährlichste, was man in Linux tun kann. Mit rm initiert man das Löschen, die Parameter -f und -r stehen für force und rekursiv, und der unscheinbare / verweist auf das Hauptverzeichnis.
Fake Check
Bisweilen kommt es vor, dass man Speicher erstanden hat, die eine hohe Kapazität anzeigen, diese Kapazitäten aber nicht im Ansatz vorhanden sind. Es handelt sich um sogenannte Fake Geräte. Das Problem dieser Fake Geräte ist, dass die Daten, die auf das Gerät geschrieben werden, für die keine Kapazität mehr vorhanden ist, im Nirwana landen. Leider erhält man keine Fehlermeldung und bemerkt das Problem oft erst, wenn man zu einem späteren Zeitpunkt wieder auf die Daten zugreifen möchte.
Ein sehr unschöner Weg, wie man an FAKE‑Geräte kommt, ist ein Hack in Amazon. Damit der Versand zuverlässig und schnell vonstattengeht, bietet Amazon für seine Händler die Option an, die Waren im eigenen Logistikcenter zu deponieren. Händler, die diese Option nutzen, werden auch bevorzugt auf der Amazon Seite angezeigt. Das Problem ist nun, dass gleiche Produkte alle in die selbe Kiste kommen, was durchaus auch Sinn ergibt. Diesen Umstand nutzen Kriminelle schamlos aus und senden an Amazon ihre FAKE-Produkte. Im Nachhinein kann man dann nicht mehr zuordnen, wer der ursprüngliche Lieferant war.
Ein weiteres Szenario für den Umgang mit Massenspeichern unter Linux sind sogenannte NAS‑Festplatten, die über ein Netzwerkkabel an den Router angeschlossen werden und dann allen Geräten wie Fernsehern etc. zur Verfügung stehen. Damit der Zugriff auf die Dateien nur für berechtigte Nutzer freigegeben wird, kann man ein Passwort festlegen. Günstige Lösungen für den Heimgebrauch gibt es zum Beispiel von Western Digital mit der Produktserie MyCloud. Nun wäre es eine sehr praktische Sache, wenn man die eigene NAS automatisch beim Bootvorgang auf seinem Linuxsystem anmeldet, sodass sie ohne weitere Anmeldung sofort benutzbar ist. Dazu muss man die URL des NAS z. B. aus der Gebrauchsanweisung oder über einen Netzwerkscan ermitteln. Hat man jetzt alle notwendigen Informationen wie URL / IP, Anmeldenamen und Passwort, kann man mit einem Eintrag in der Datei /etc/fstab das NAS registrieren. Die Datei fstab haben wir bereits im Abschnitt über die SWAP Datei kennengelernt.
Zuerst installieren wir für einen problemlosen Zugriff auf die für NAS Systeme üblichen Dateisysteme NFS Unterstützung für Linux.
Im nächsten Schritt müssen wir eine Datei anlegen, die den automatischen Login ermöglicht. Diese Datei nennen wir nas-login und speichern sie unter /etc/nas-login. Der Inhalt dieser Datei sind unsere Login Informationen.
user=accountname
password=s3cr3t
Abschließend editieren wir die Datei fstab und fügen als letzte Zeile folgende Information hinzu:
Das Beispiel ist für eine Western Digital MyCloud Platte, die über die URL //wdmycloud.local/account erreichbar ist. Account ist an den entsprechenden Benutzer anzupassen. Der Mountpoint unter Linux lautet /media/nas. In den meisten Fällen muss man dieses Verzeichnis vorher mit sudo mkdir /media/nas erstellen. In den Credentials tragen wir die Datei mit unseren Anmeldeinformationen /etc/nas-login ein. Nach einem Reboot wird der Nasspeicher im Dateibrowser angezeigt und kann verwendet werden. Je nach Netzwerkgeschwindigkeit kann das den Bootvorgang um ein paar Sekunden verlängern. Noch länger dauert es, wenn der Rechner nicht mit dem heimischen Netzwerk verbunden ist und das NAS nicht verfügbar ist. Man kann sich mit einem Raspberry Pi auch sein eigenes NAS bauen, das kann aber Stoff für einen zukünftigen Artikel sein.
Anschließend möchte ich noch ein paar Worte zum Service von Western Digital verlieren. Ich hatte bereits 2 Tauschgeräte, die jedes Mal problemlos durch WD ersetzt worden sind. Natürlich habe ich dem Service im Vorfeld meine Analysen per Screenshot übermittelt, wodurch unsachgemäßer Gebrauch durch mich ausgeschlossen werden konnte. Die in diesem Artikel vorgestellten Techniken haben mir dabei sehr geholfen, weswegen ich überhaupt auf die Idee gekommen bin, diesen Text zu verfassen. Damit will ich es auch belassen und hoffe, euch leisten die hier zusammengetragenen Informationen ebenso hilfreiche Dienste wie mir.
Wer in seiner Anwendung konfigurierbare bzw. veränderliche Einstellungen benötigt kann nicht immer auf Datenbanken zurückgreifen. In diesem Artikel bespreche ich…
Damit wir Konsolenprogramme systemweit direkt aufrufen können, ohne dass wir dazu den vollständigen Pfad angeben müssen, bedienen wir uns der sogenannten Pfadvariable. Wir speichern also in dieser Pfadvariable den gesamten Pfad inklusive des ausführbaren Programmes, der sogenannten Executable, um auf der Kommandozeile den Pfad inklusive der Executable nicht mehr mit angeben zu müssen. Übrigens leitet sich aus dem Wort executable die in Windows übliche Dateierweiterung exe ab. Hier haben wir auch einen signifikanten Unterschied zwischen den beiden Betriebssystemen Windows und Linux. Während Windows über die Dateiendung wie beispielsweise exe oder txt weiß, ob es sich um eine reine ASCII Textdatei oder um eine ausführbare Datei handelt, nutzt Linux die Metainformationen der Datei, um diese Unterscheidung zu machen. Deswegen ist es unter Linux eher unüblich, diese Dateiendungen txt und exe zu verwenden.
Typische Anwendungsfälle für das Setzen der Pfadvariable sind Programmiersprachen wie Java oder Werkzeuge wie das Buildwerkzeug Maven. Wenn wir zum Beispiel Maven von der offiziellen Homepage heruntergeladen haben, können wir das Programm an einer beliebigen Stelle auf unserem System entpacken. Unter Linux könnte der Ort /opt/maven und unter Microsoft Windows C:/Programme/Maven lauten. In diesem Installationsverzeichnis gibt es wiederum ein Unterverzeichnis /bin in dem die ausführbaren Programme liegen. Die Executable für Maven heißt mvn und um etwa die Version auszugeben, wäre unter Linux ohne den Eintrag in der Pfadvariablen das Kommando wie folgt: /opt/maven/bin/mvn -v. Also ein wenig lang, wie wir durchaus zugeben können. Der Eintrag des Installationsverzeichnisses von Maven in den Pfad verkürzt den gesamten Befehl auf mvn -v. Dieser Mechanismus gilt übrigens für alle Programme, die wir als Befehl in der Konsole verwenden.
Bevor ich dazu komme, wie die Pfadvariable unter Linux, als auch unter Windows angepasst werden kann, möchte ich noch ein weiteres Konzept, die Systemvariable, vorstellen. Systemvariablen sind globale Variablen, die uns in der Bash zur Verfügung stehen. Die Pfadvariable zählt auch als Systemvariable. Eine andere Systemvariable ist HOME, welche auf das Stammverzeichnis des angemeldeten Benutzers zeigt. Systemvariablen werden großgeschrieben und die Wörter mit einem Unterstrich getrennt. Für unser Beispiel mit dem Eintragen der Maven Executable in den Pfad, können wir auch eine eigene Systemvariable setzen. Hier gibt es für Maven die Konvention M2_HOME und für Java gilt JAVA_HOME. Als best practice bindet man das Installationsverzeichnis an eine Systemvariable und nutzt dann die selbst definierte Systemvariable, um den Pfad zu erweitern. Dieses Vorgehen ist recht typisch für Systemadministratoren, die ihre Serverinstallation mithilfe von Systemvariablen vereinfachen. Denn diese Systemvariablen sind global und können von Automatisierungsskripten auch ausgelesen werden.
Die Kommandozeile, oder auch Shell, Bash, Konsole und Terminal genannt, bietet mit echo eine einfache Möglichkeit, den Wert der Systemvariablen auszugeben. Am Beispiel der Pfadvariable sehen wir auch gleich den Unterschied zu Linux und Windows. Linux: echo $PATH Windows: echo %PATH%
Beginnen wir auch nun gleich mit der einfachsten Möglichkeit, die Pfadvariable zu setzen. Unter Linux müssen wir lediglich die versteckte Datei .bashrc editieren. Am Ende der Datei fügen wir folgende Zeilen hinzu und speichern den Inhalt.
Wir binden an die Variable M2_HOME das Installationsverzeichnis. Anschließend erweitern wir die Pfadvariable um um die M2_HOME Systemvariable mit dem Zusatz zum Unterverzeichnis der ausführbaren Dateien. Dieses Vorgehen ist auch bei Windows Systemen üblich, da sich so der Installationspfad einer Anwendung schneller finden und auch anpassen lässt. Nach dem Ändern der Datei .bashrc muss das Terminal neu gestartet werden, damit die Änderungen wirksam werden. Dieses Vorgehen stellt sicher, dass auch nach einem Neustart des Rechners die Einträge nicht verloren gehen.
Unter Windows besteht die Herausforderung darin, lediglich die Eingabemaske zu finden, wo die Systemvariablen gesetzt werden können. In diesem Artikel beschränke ich mich auf die Variante für Windows 11. Es kann natürlich sein, dass sich bei einem künftigen Update der Weg, die Systemvariablen zu editieren, geändert hat. Zwischen den einzelnen Windows Versionen gibt es leichte Variationen. Die Einstellung gilt dann sowohl für die CMD als auch für die PowerShell. Der nachfolgende Screenshot zeigt, wie man in Windows 11 zu den Systemeinstellungen gelangt.
Dazu klicken wir auf einen leeren Bereich auf dem Desktop die rechte Maustaste und wählen den Eintrag System aus. Im Untermenü System – Über finden sich die Systemeinstellungen, die das Popup Systemproperties öffnen. In den Systemeinstellungen drücken wir den Knopf Umgebungsvariablen, um die finale Eingabemaske zu erhalten. Nach den entsprechenden Anpassungen muss ebenfalls die Konsole neu gestartet werden, um die Änderungen wirksam werden zu lassen.
In dieser kleinen Hilfe haben wir den Zweck von Systemvariablen kennengelernt und wie man diese dauerhaft unter Linux und Windows speichert. Den Erfolg unserer Anstrengungen können wir in der Shell anschließend zügig über echo mit der Ausgabe des Inhalts der Variablen kontrollieren. Und schon sind wir dem IT-Profi wieder einen Schritt nähergekommen.
Wir haben bereits mit GPT4all eine Anleitung, wie man ein eigenes lokales LLM betreiben kann. Leider gibt es bei der vorangegangenen Lösung eine kleine Einschränkung. Es können keine Dokumente wie PDF verarbeitet werden. In diesem neuen Workshop installieren wir AnythingLLM mit Ollama um Dokumente analysieren zu können.
Auch für diesen Workshop gilt als Mindestvoraussetzung ein Computer mit 16 GB RAM auf dem optimalerweise ein Linux (Mint, Ubuntu oder Debian) installiert ist. Mit einigen Anpassungen kann diese Anleitung auf Windows und Apple Computer ebenfalls durchgeführt werden. Je geringer die Hardwareressourcen sind, um so länger dauern die Antwortzeiten.
Beginnen wir auch gleich mit dem ersten Schritt und installieren Ollama. Dazu öffnen wir die Bash und benötigen folgendes Kommando: sudo curl -fsSL https://ollama.com/install.sh | sh. Der Befehl bewirkt, das Ollama heruntergeladen wird und das Installationsscript ausgeführt wird. Damit die Installation auch beginnt, muss noch das Administratorkennwort eingegeben werden. Ollama ist ein Kommandozeilenprogramm, das über die Konsole gesteuert wird. Nach erfolgreicher Installation muss noch ein Sprachmodell geladen werden. Auf der Internetseite https://ollama.com/search sind entsprechende Modelle zu finden.
Bewährte Sprachmodelle sind:
lama 3.1 8B: Leistungsstark für anspruchsvollere Anwendungen.
Phi-3-5 3B: Gut geeignet für logisches Denken und Mehrsprachigkeit.
Llama 3.3 2B: Effizient für Anwendungen mit begrenzten Ressourcen.
Phi 4 14B: State-of-the-art Modell mit erhöhter Hardware-Anforderung aber Leistung vergleichbar mit deutlich größeren Modellen.
Nachdem man sich für ein Sprachmodell entschieden hat, kann man den entsprechenden Befehl aus der Übersicht kopieren und in das Terminal eingeben. Für unser Beispiel soll das zu Demonstrationszwecken DeepSeek R1 sein.
Wie im Screenshot zu sehen ist lautet der entsprechende Befehl, den wir benötigen, um das Modell lokal in Ollama zu installieren: ollama run deepseek-r1. Die Installation des Sprachmodells kann ein wenig Zeit in Anspruch nehmen, Das hängt von der Internetverbindung und der Geschwindigkeit des Rechners ab. Nachdem das Modell lokal in Ollama installiert wurde, können wir das Terminal wieder schließen und zum nächsten Schritt übergehen, der Installation von AnythingLLM
Die Installation von AnythingLLm erfolgt ganz analog zu der Installation von Ollama. Dazu öffen wir das Terminal und geben folgenden Befehl ein: curl -fsSL https://cdn.anythingllm.com/latest/installer.sh | sh. Wenn die Installation abgeschlossen ist, können wir in das Installationsverzeichnis wechseln, welches in der Regel /home/<user>/AnythingLLMDesktop ist. Dort navigieren wir zum Link start und machen diese ausführbar (rechtsklick und Eigenschaften auswählen) und erstellen noch zusätzlich eine Verknüpfung auf dem Desktop. Nun können wir AnythingLLM bequem vom Desktop aus starten, was wir auch gleich tun.
Nachdem wir den Workspace festgelegt haben, können wir Anything nun mit Ollama verknüpfen. Dazu gehen wir auf das kleine Schraubenschlüssel Icon (Einstellungen) im linken unteren Bereich. Dort wählen wir den Eintrag LLM und wählen Ollama aus. Nun können wir das für Ollama hinterlegte Sprachmodell auswählen. Jetzt speichern wir unsere Einstellung ab. Nun kann man in den Chatmodus wechseln. Es besteht natürlich jederzeit die Möglichkeit, das Sprachmodell zu wechseln. Im Gegensatz zu vorhergehenden Workshop können wir jetzt PDF Dokumente hochladen und zum Inhalt Fragen stellen. Viel Spaß damit.
Auch wenn zur Qualitätssteigerung der Software- Projekte in den letzten Jahren ein erheblicher Mehraufwand für das Testen betrieben wurde [1], ist der Weg zu kontinuierlich wiederholbaren Erfolgen keine Selbstverständlichkeit. Stringentes und zielgerichtetes Management aller verfügbaren Ressourcen war und ist bis heute unverzichtbar für reproduzierbare Erfolge.
(c) 2016 Marco Schulz, Java aktuell Ausgabe 4, S.14-19
Es ist kein Geheimnis, dass viele IT-Projekte nach wie vor ihre liebe Not haben, zu einem erfolgreichen Abschluss zu gelangen. Dabei könnte man durchaus meinen, die vielen neuen Werkzeuge und Methoden, die in den letzten Jahren aufgekommen sind, führten wirksame Lösungen ins Feld, um der Situation Herr zu werden. Verschafft man sich allerdings einen Überblick zu aktuellen Projekten, ändert sich dieser Eindruck.
Der Autor hat öfter beobachten können, wie diese Problematik durch das Einführen neuer Werkzeuge beherrscht werden sollte. Nicht selten endeten die Bemühungen in Resignation. Schnell entpuppte sich die vermeintliche Wunderlösung als schwergewichtiger Zeiträuber mit einem enormen Aufwand an Selbstverwaltung. Aus der anfänglichen Euphorie aller Beteiligten wurde schnell Ablehnung und gipfelte nicht selten im Boykott einer Verwendung. So ist es nicht verwunderlich, dass erfahrene Mitarbeiter allen Veränderungsbestrebungen lange skeptisch gegenüberstehen und sich erst dann damit beschäftigen, wenn diese absehbar erfolgreich sind. Aufgrund dieser Tatsache hat der Autor als Titel für diesen Artikel das provokante Zitat von Grady Booch gewählt, einem Mitbegründer der UML.
Oft wenden Unternehmen zu wenig Zeit zum Etablieren einer ausgewogenen internen Infrastruktur auf. Auch die Wartung bestehender Fragmente wird gern aus verschiedensten Gründen verschoben. Auf Management-Ebene setzt man lieber auf aktuelle Trends, um Kunden zu gewinnen, die als Antwort auf ihre Ausschreibung eine Liste von Buzzwords erwarten. Dabei hat es Tom De Marco bereits in den 1970er-Jahren ausführlich beschrieben [2]: Menschen machen Projekte (siehe Abbildung 1).
Wir tun, was wir können, aber können wir etwas tun?
Das Vorhaben, trotz bester Absichten und intensiver Bemühungen ein glückliches Ende finden, ist leider nicht die Regel. Aber wann kann man in der Software-Entwicklung von einem gescheiterten Projekt sprechen? Ein Abbruch aller Tätigkeiten wegen mangelnder Erfolgsaussichten ist natürlich ein offensichtlicher Grund, in diesem Zusammenhang allerdings eher selten. Vielmehr gewinnt man diese Erkenntnis während der Nachbetrachtung abgeschlossener Aufträge. So kommen beispielsweise im Controlling bei der Ermittlung der Wirtschaftlichkeit Schwachstellen zutage.
Gründe für negative Ergebnisse sind meist das Überschreiten des veranschlagten Budgets oder des vereinbarten Fertigstellungstermins. Üblicherweise treffen beide Bedingungen gleichzeitig zu, da man der gefährdeten Auslieferungsfrist mit Personal-Aufstockungen entgegenwirkt. Diese Praktik erreicht schnell ihre Grenzen, da neue Teammitglieder eine Einarbeitungsphase benötigen und so die Produktivität des vorhandenen Teams sichtbar reduzieren. Einfach zu benutzende Architekturen und ein hohes Maß an Automatisierung mildern diesen Effekt etwas ab. Hin und wieder geht man auch dazu über, den Auftragnehmer auszutauschen, in der Hoffnung, dass neue Besen besser kehren.
Wie eine fehlende Kommunikation, unzureichende Planung und schlechtes Management sich negativ auf die äußere Wahrnehmung von Projekten auswirkt, zeigt ein kurzer Blick auf die Top-3-Liste der in Deutschland fehlgeschlagenen Großprojekte: Berliner Flughafen, Hamburger Elbphilharmonie und Stuttgart 21. Dank ausführlicher Berichterstattung in den Medien sind diese Unternehmungen hinreichend bekannt und müssen nicht näher erläutert werden. Auch wenn die angeführten Beispiele nicht aus der Informatik stammen, finden sich auch hier die stets wiederkehrenden Gründe für ein Scheitern durch Kostenexplosion und Zeitverzug.
Abbildung 1: Problemlösung – „A bisserl was geht immer“, Monaco Franze
Der Wille, etwas Großes und Wichtiges zu erschaffen, allein genügt nicht. Die Verantwortlichen benötigen auch die notwendigen fachlichen, planerischen, sozialen und kommunikativen Kompetenzen, gepaart mit den Befugnissen zum Handeln. Luftschlösser zu errichten und darauf zu warten, dass Träume wahr werden, beschert keine vorzeigbaren Resultate.
Große Erfolge werden meist dann erzielt, wenn möglichst wenige Personen bei Entscheidungen ein Vetorecht haben. Das heißt nicht, dass man Ratschläge ignorieren sollte, aber auf jede mögliche Befindlichkeit kann keine Rücksicht genommen werden. Umso wichtiger ist es, wenn der Projektverantwortliche die Befugnis hat, seine Entscheidung durchzusetzen, dies jedoch nicht mit aller Härte demonstriert.
Es ist völlig normal, wenn man als Entscheidungsträger nicht sämtliche Details beherrscht. Schließlich delegiert man die Umsetzung an die entsprechenden Spezialisten. Dazu ein kurzes Beispiel: Als sich in den frühen 2000er-Jahren immer bessere Möglichkeiten ergaben, größere und komplexere Web-Anwendungen zu erstellen, kam in Meetings oft die Frage auf, mit welchem Paradigma die Anzeigelogik umzusetzen sei. Die Begriffe „Multi Tier“, „Thin Client“ und „Fat Client“ dominierten zu dieser Zeit die Diskussionen der Entscheidungsgremien. Dem Auftraggeber die Vorteile verschiedener Schichten einer verteilten Web-Applikation zu erläutern, war die eine Sache. Einem technisch versierten Laien aber die Entscheidung zu überlassen, wie er auf seine neue Applikation zugreifen möchte – per Browser („Thin Client“) oder über eine eigene GUI („Fat Client“) –, ist schlicht töricht. So galt es in vielen Fällen, während der Entwicklung auftretende Missverständnisse auszuräumen. Die schmalgewichtige Browser-Lösung entpuppte sich nicht selten als schwer zu beherrschende Technologie, da Hersteller sich selten um Standards kümmerten. Dafür bestand üblicherweise eine der Hauptanforderungen darin, die Applikation in den gängigsten Browsern nahezu identisch aussehen zu lassen. Das ließ sich allerdings nur mit erheblichem Mehraufwand umsetzen. Ähnliches konnte beim ersten Hype der Service-orientierten Architekturen beobachtet werden.
Die Konsequenz aus diesen Beobachtungen zeigt, dass es unverzichtbar ist, vor dem Projektstart eine Vision zu erarbeiten, deren Ziele auch mit dem veranschlagten Budget übereinstimmen. Eine wiederverwendbare Deluxe-Variante mit möglichst vielen Freiheitsgraden erfordert eine andere Herangehensweise als eine „We get what we need“-Lösung. Es gilt, sich weniger in Details zu verlieren, als das große Ganze im Blick zu halten.
Besonders im deutschsprachigen Raum fällt es Unternehmen schwer, die notwendigen Akteure für eine erfolgreiche Projektumsetzung zu finden. Die Ursachen dafür mögen recht vielfältig sein und könnten unter anderem darin begründet sein, dass Unternehmen noch nicht verstanden haben, dass Experten sich selten mit schlecht informierten und unzureichend vorbereiteten Recruitment-Dienstleistern unterhalten möchten.
Getting things done!
Erfolgreiches Projektmanagement ist kein willkürlicher Zufall. Schon lange wurde ein unzureichender Informationsfluss durch mangelnde Kommunikation als eine der negativen Ursachen identifiziert. Vielen Projekten wohnt ein eigener Charakter inne, der auch durch das Team geprägt ist, das die Herausforderung annimmt, um gemeinsam die gestellte Aufgabe zu bewältigen. Agile Methoden wie Scrum [3], Prince2 [4] oder Kanban [5] greifen diese Erkenntnis auf und bieten potenzielle Lösungen, um IT-Projekte erfolgreich durchführen zu können.
Gelegentlich ist jedoch zu beobachten, wie Projektleiter unter dem Vorwand der neu eingeführten agilen Methoden die Planungsaufgaben an die zuständigen Entwickler zur Selbstverwaltung übertragen. Der Autor hat des Öfteren erlebt, wie Architekten sich eher bei Implementierungsarbeiten im Tagesgeschäft gesehen haben, anstatt die abgelieferten Fragmente auf die Einhaltung von Standards zu überprüfen. So lässt sich langfristig keine Qualität etablieren, da die Ergebnisse lediglich Lösungen darstellen, die eine Funktionalität sicherstellen und wegen des Zeit- und Kostendrucks nicht die notwendigen Strukturen etablieren, um die zukünftige Wartbarkeit zu gewährleisten. Agil ist kein Synonym für Anarchie. Dieses Setup wird gern mit einem überfrachteten Werkzeugkasten voller Tools aus dem DevOps-Ressort dekoriert und schon ist das Projekt scheinbar unsinkbar. Wie die Titanic!
Nicht ohne Grund empfiehlt man seit Jahren, beim Projektstart allerhöchstens drei neue Technologien einzuführen. In diesem Zusammenhang ist es auch nicht ratsam, immer gleich auf die neuesten Trends zu setzen. Bei der Entscheidung für eine Technologie müssen im Unternehmen zuerst die entsprechenden Ressourcen aufgebaut sein, wofür hinreichend Zeit einzuplanen ist. Die Investitionen sind nur dann nutzbringend, wenn die getroffene Wahl mehr als nur ein kurzer Hype ist. Ein guter Indikator für Beständigkeit sind eine umfangreiche Dokumentation und eine aktive Community. Diese offenen Geheimnisse werden bereits seit Jahren in der einschlägigen Literatur diskutiert.
Wie geht man allerdings vor, wenn ein Projekt bereits seit vielen Jahren etabliert ist, aber im Sinne des Produkt-Lebenszyklus ein Schwenk auf neue Techniken unvermeidbar wird? Die Gründe für eine solche Anstrengung mögen vielseitig sein und variieren von Unternehmen zu Unternehmen. Die Notwendigkeit, wichtige Neuerungen nicht zu verpassen, um im Wettbewerb weiter bestehen zu können, sollte man nicht zu lange hinauszögern. Aus dieser Überlegung ergibt sich eine recht einfach umzusetzende Strategie. Aktuelle Versionen werden in bewährter Tradition fortgesetzt und erst für das nächste beziehungsweise übernächste Major-Release wird eine Roadmap erarbeitet, die alle notwendigen Punkte enthält, um einen erfolgreichen Wechsel durchzuführen. Dazu erarbeitet man die kritischen Punkte und prüft in kleinen Machbarkeitsstudien, die etwas anspruchsvoller als ein „Hallo Welt“- Tutorial sind, wie eine Umsetzung gelingen könnte. Aus Erfahrung sind es die kleinen Details, die das Krümelchen auf der Waagschale sein können, um über Erfolg oder Misserfolg zu entscheiden.
Bei allen Bemühungen wird ein hoher Grad an Automatisierung angestrebt. Gegenüber stetig wiederkehrenden, manuell auszuführenden Aufgaben bietet Automatisierung die Möglichkeit, kontinuierlich wiederholbare Ergebnisse zu produzieren. Dabei liegt es allerdings in der Natur der Sache, dass einfache Tätigkeiten leichter zu automatisieren sind als komplexe Vorgänge. Hier gilt es, zuvor die Wirtschaftlichkeit der Vorhaben zu prüfen, sodass Entwickler nicht gänzlich ihrem natürlichen Spieltrieb frönen und auch unliebsame Tätigkeiten des Tagesgeschäfts abarbeiten.
Wer schreibt, der bleibt
Dokumentation, das leidige Thema, erstreckt sich über alle Phasen des Software-Entwicklungsprozesses. Ob für API-Beschreibungen, das Benutzer-Handbuch, Planungsdokumente zur Architektur oder erlerntes Wissen über optimales Vorgehen – das Beschreiben zählt nicht zu den favorisierten Aufgaben aller beteiligten Protagonisten. Dabei lässt sich oft beobachten, dass anscheinend die landläufige Meinung vorherrscht, dicke Handbücher ständen für eine umfangreiche Funktionalität des Produkts. Lange Texte in einer Dokumentation sind jedoch eher ein Qualitätsmangel, der die Geduld des Lesers strapaziert, weil dieser eine präzise auf den Punkt kommende Anleitung erwartet. Stattdessen erhält er schwammige Floskeln mit trivialen Beispielen, die selten problemlösend sind.
Abbildung 2: Test Coverage mit Cobertura
Diese Erkenntnis lässt sich auch auf die Projekt-Dokumentation übertragen und wurde unter anderem von Johannes Sidersleben [6] unter der Metapher über viktorianische Novellen ausführlich dargelegt. Hochschulen haben diese Erkenntnisse bereits aufgegriffen. So hat beispielsweise die Hochschule Merseburg den Studiengang „Technische Redaktion“ [7] etabliert. Es bleibt zu hoffen, zukünftig mehr Absolventen dieses Studiengangs in der Projekt-Landschaft anzutreffen.
Bei der Auswahl kollaborativer Werkzeuge als Wissensspeicher ist immer das große Ganze im Blick zu halten. Erfolgreiches Wissensmanagement lässt sich daran messen, wie effizient ein Mitarbeiter die gesuchte Information findet. Die unternehmensweite Verwendung ist aus diesem Grund eine Managemententscheidung und für alle Abteilungen verpflichtend.
Informationen haben ein unterschiedliches Naturell und variieren sowohl in ihrem Umfang als auch bei der Dauer ihrer Aktualität. Daraus ergeben sich verschiedene Darstellungsformen wie Wiki, Blog, Ticketsystem, Tweets, Foren oder Podcasts, um nur einige aufzuzählen. Foren bilden sehr optimal die Frage- und Antwort-Problematik ab. Ein Wiki eignet sich hervorragend für Fließtext, wie er in Dokumentationen und Beschreibungen vorkommt. Viele Webcasts werden als Video angeboten, ohne dass die visuelle Darstellung einen Mehrwert bringt. Meist genügt eine gut verständliche und ordentlich produzierte Audiospur, um Wissen zu verteilen. Mit einer gemeinsamen und normierten Datenbasis lassen sich abgewickelte Projekte effizient miteinander vergleichen. Die daraus resultierenden Erkenntnisse bieten einen hohen Mehrwert bei der Erstellung von Prognosen für zukünftige Vorhaben.
Test & Metriken − das Maß aller Dinge
Bereits beim Überfliegen des Quality Reports 2014 erfährt man schnell, dass der neue Trend „Software testen“ ist. Unternehmen stellen vermehrt Kontingente dafür bereit, die ein ähnliches Volumen einnehmen wie die Aufwendungen für die Umsetzung des Projekts. Genau genommen löscht man an dieser Stelle Feuer mit Benzin. Bei tieferer Betrachtung wird bereits bei der Planung der Etat verdoppelt. Es liegt nicht selten im Geschick des Projektleiters, eine geeignete Deklarierung für zweckgebundene Projektmittel zu finden.
Nur deine konsequente Überprüfung der Testfall-Abdeckung durch geeignete Analyse-Werkzeuge stellt sicher, dass am Ende hinreichend getestet wurde. Auch wenn man es kaum glauben mag: In einer Zeit, in der Software-Tests so einfach wie noch nie erstellt werden können und verschiedene Paradigmen kombinierbar sind, ist eine umfangreiche und sinnvolle Testabdeckung eher die Ausnahme (siehe Abbildung 2).
Es ist hinreichend bekannt, dass sich die Fehlerfreiheit einer Software nicht beweisen lässt. Anhand der Tests weist man einzig ein definiertes Verhalten für die erstellten Szenarien nach. Automatisierte Testfälle ersetzen in keinem Fall ein manuelles Code-Review durch erfahrene Architekten. Ein einfaches Beispiel dafür sind in Java hin und wieder vorkommende verschachtelte „try catch“-Blöcke, die eine direkte Auswirkung auf den Programmfluss haben. Mitunter kann eine Verschachtelung durchaus gewollt und sinnvoll sein. In diesem Fall beschränkt sich die Fehlerbehandlung allerdings nicht einzig auf die Ausgabe des Stack-Trace in ein Logfile. Die Ursache dieses Programmierfehlers liegt in der Unerfahrenheit des Entwicklers und dem an dieser Stelle schlechten Ratschlag der IDE, für eine erwartete Fehlerbehandlung die Anweisung mit einem eigenen „try catch“-Block zu umschliessen, anstatt die vorhandene Routine durch ein zusätzliches „catch“-Statement zu ergänzen. Diesen offensichtlichen Fehler durch Testfälle erkennen zu wollen, ist aus wirtschaftlicher Betrachtung ein infantiler Ansatz.
Typische Fehlermuster lassen sich durch statische Prüfverfahren kostengünstig und effizient aufdecken. Publikationen, die sich besonders mit Codequalität und Effizienz der Programmiersprache Java beschäftigen [8, 9, 10], sind immer ein guter Ansatzpunkt, um eigene Standards zu erarbeiten.
Sehr aufschlussreich ist auch die Betrachtung von Fehlertypen. Beim Issue-Tracking und bei den Commit-Messages in SCM-Systemen der Open-Source-Projekte wie Liferay [11] oder GeoServer [12] stellt man fest, dass ein größerer Teil der Fehler das Grafische User Interface (GUI) betreffen. Dabei handelt es sich häufig um Korrekturen von Anzeigetexten in Schaltflächen und Ähnlichem. Die Meldung vornehmlicher Darstellungsfehler kann auch in der Wahrnehmung der Nutzer liegen. Für diese ist das Verhalten einer Anwendung meist eine Black Box, sodass sie entsprechend mit der Software umgehen. Es ist durchaus nicht verkehrt, bei hohen Nutzerzahlen davon auszugehen, dass die Anwendung wenig Fehler aufweist.
Das übliche Zahlenwerk der Informatik sind Software-Metriken, die dem Management ein Gefühl über die physische Größe eines Projekts geben können. Richtig angewendet, liefert eine solche Übersicht hilfreiche Argumente für Management-Entscheidungen. So lässt sich beispielsweise über die zyklische Komplexität nach McCabe [13] die Anzahl der benötigten Testfälle ableiten. Auch eine Statistik über die Lines of Code und die üblichen Zählungen der Packages, Klassen und Methoden zeigt das Wachstum eines Projekts und kann wertvolle Informationen liefern.
Eine sehr aufschlussreiche Verarbeitung dieser Informationen ist das Projekt Code-City [14], das eine solche Verteilung als Stadtplan visualisiert. Es ist eindrucksvoll Abbildung 3: Maven JDepend Plugin – Zahlen mit wenig Aussagekraft zu erkennen, an welchen Stellen gefährliche Monolithe entstehen können und wo verwaiste Klassen beziehungsweise Packages auftreten.
Abbildung 3: Maven JDepend Plugin – Zahlen mit wenig Aussagekraft
Fazit
Im Tagesgeschäft begnügt man sich damit, hektische Betriebsamkeit zu verbreiten und eine gestresste Miene aufzusetzen. Durch das Produzieren unzähliger Meter Papier wird anschließend die persönliche Produktivität belegt. Die auf diese Art und Weise verbrauchte Energie ließe sich durch konsequent überlegtes Vorgehen erheblich sinnvoller einsetzen.
Frei nach Kants „Sapere Aude“ sollten einfache Lösungen gefördert und gefordert werden. Mitarbeiter, die komplizierte Strukturen benötigen, um die eigene Genialität im Team zu unterstreichen, sind möglicherweise keine tragenden Pfeiler, auf denen sich gemeinsame Erfolge aufbauen lassen. Eine Zusammenarbeit mit unbelehrbaren Zeitgenossen ist schnell überdacht und gegebenenfalls korrigiert.
Viele Wege führen nach Rom – und Rom ist auch nicht an einem Tag erbaut worden. Es lässt sich aber nicht von der Hand weisen, dass irgendwann der Zeitpunkt gekommen ist, den ersten Spatenstich zu setzen. Auch die Auswahl der Wege ist kein unentscheidbares Problem. Es gibt sichere Wege und gefährliche Pfade, auf denen auch erfahrene Wanderer ihre liebe Not haben, sicher das Ziel zu erreichen.
Für ein erfolgreiches Projektmanagement ist es unumgänglich, den Tross auf festem und stabilem Grund zu führen. Das schließt unkonventionelle Lösungen nicht grundsätzlich aus, sofern diese angebracht sind. Die Aussage in Entscheidungsgremien: „Was Sie da vortragen, hat alles seine Richtigkeit, aber es gibt in unserem Unternehmen Prozesse, auf die sich Ihre Darstellung nicht anwenden lässt“, entkräftet man am besten mit dem Argument: „Das ist durchaus korrekt, deswegen ist es nun unsere Aufgabe, Möglichkeiten zu erarbeiten, wie wir die Unternehmensprozesse entsprechend bekannten Erfolgsstories adaptieren, anstatt unsere Zeit darauf zu verwenden, Gründe aufzuführen, damit alles beim Alten bleibt. Sie stimmen mir sicherlich zu, dass der Zweck unseres Treffens darin besteht, Probleme zu lösen, und nicht, sie zu ignorieren.“ … more voice
Für die Integration in IDEs ist es unerheblich, bei welcher IDE Ihre persönlichen Präferenzen angesiedelt sind, der Funktionsumfang der Integration ist in beiden IDEs weitgehend identisch und unterscheidet sich nur in Details. Während NetBeans von Haus aus Maven-Projekte unterstützt, ist für die meisten Eclipse-Distributionen die zusätzliche Installation des Eclipse-Maven-Plug-ins m2e notwendig.
Der Vorteil, die Funktionalitäten von Maven innerhalb einer IDE nutzen zu können, ist enorm. Ein Aspekt ist beispielsweise der Import bestehender Maven-Projekte in die Entwicklungsumgebung. Anhand der POM werden die notwendigen Konfigurationen des gesamten Projekts wie zum Beispiel Verzeichnisse für Sourcen, Test und Dependencies aus der POM gelesen. Ein mühseliges Adaptieren der Projekteigenschaften nach einem Import entfällt ebenso wie das Verteilen der IDE-Konfiguration über das Konfigurationsmanagement. Dadurch hat der Entwickler mehr Freiheit bei der Wahl seiner Entwicklungsumgebung. Eine Grundvoraussetzung für den erfolgreichen Import eines Projekts in eine IDE ist, dass die verwendeten Dependencies lokal oder remote verfügbar sind. Hin und wieder kommt es vor, dass einzelne Artefakte manuell in das lokale Repository installiert werden müssen. Diese Aufgabe lässt sich in beiden IDEs sehr komfortabel mit wenigen Mausklicks bewerkstelligen und ein optisches Feedback des Erfolgs kann über die Views der Repository-Browser eingeholt werden.
Ältere Projekte, die nicht im Maven-Format vorliegen und damit nicht die notwendige Verzeichnisstruktur und POM aufweisen, lassen sich in den meisten Fällen über die Konsole automatisiert migrieren. Der schnellere Weg ist allerdings eine manuelle Migration, da die automatisch generierte POM in aller Regel im Nachhinein weiter von Hand angepasst werden muss. Über Archetypes werden die Verzeichnisstruktur und die POM erzeugt. Im zweiten Schritt sind die Sourcen et cetera in die entsprechenden Verzeichnisse zu kopieren, um abschließend die Dependencies zu konfigurieren. In späteren Arbeitsschritten kann die POM den Projektanforderungen weiter angepasst werden.
Eine wichtige Eigenschaft ist unter anderem auch die Möglichkeit, das vorhandene Maven Build-in der IDEs durch eine eigene Maven-Installation auszutauschen. Der Vorteil einer externen Installation ergibt sich aus dem größtmöglichen Einfluss auf den Entwicklungsprozess, da beispielsweise festgelegt wird, welche Version von Maven verwendet wird. Vor allem, wenn stets auf die neueste Version zurückgegriffen werden soll, ist diese Option von unschätzbarem Wert, das es meist einige Zeit dauert, bis das entsprechende Plug-in aktualisiert wird.
Die größten Unterschiede zwischen NetBeans und Eclipse finden sich bei der Bearbeitung der POM. Während NetBeans auf eine Code-Vervollständigung setzt, bietet Eclipse einen grafischen POM-Editor. Für den korrekten Betrieb von Maven ist die Auszeichnung der Schemadefinition der POM nicht notwendig. Das Weglassen der XML-Schemadefinition quittiert Eclipse mit einer Fehlerausgabe, die folgende Auszeichnung des <project> Tags beendet die Belästigung umgehend:
Das Anstoßen der einzelnen Build-Lifecycles aus Eclipse oder NetBeans heraus ist mittlerweile recht intuitiv. Der Übersichtlichkeit wegen werden nur die wichtigsten Phasen der Lifecycles zum direkten Ausführen über die Toolbar beziehungsweise das Kontextmenü angeboten. Dazu zählen vor allem Build, Clean, Clean Build und Test. Wenn dennoch einmal ein spezielles Goal gestartet werden muss, bieten beide IDEs die Möglichkeit, über einen Wizard die entsprechende Phase mit dem gewünschten Goal zu konfigurieren und auszuführen. Im Screenshot ist beispielhaft die Run-Konfiguration von Eclipse abgebildet. Für php-maven Projekte existiert ein Eclipse-Plug-in, das von Martin Eisengart entwickelt wurde. Aktuell ist dazu eine neue Version für Eclipse Indigo erschienen. Eine wichtige Eigenschaft dieses Plug-ins ist die Konvertierungsfunktion für Maven-Projekte nach php-maven. Nach erfolgreicher Konvertierung zeigt Eclipse in der View Problems den Fehler, dass das maven-plugin-Plug-in nicht ausgeführt werden kann. Diese Meldung ist kein wirklicher Fehler, sondern ergibt sich aus den Restriktionen des m2e-Plug-ins, das für alle unbekannten Plug-ins Fehler ausgibt.
Sehr komfortabel ist das Generieren der Site über das Plug-in. Dazu hält der Menüeintrag die Punkte generate, view und deploy bereit. Besonders angenehm ist die Option, die generierte Seite im Browser auszugeben, ohne umständlich über das Target-Verzeichnis navigieren zu müssen.
Wenn die Testfälle über das Kontextmenü in das Projekt eingebunden wurden, kann die View PHPUnit die wichtigsten Informationen der durchlaufenen Testfälle visualisieren. Neben den Testergebnissen wird auch eine Coverage ausgegeben (Bild 6).
Berichtswesen
Neben dem Build- und Clean-Lifecycle existiert als Dritter im Bunde der Site-Lifecycle, mit dem Reports und sogar komplette Webseiten automatisch generiert werden können. Ein gutes Beispiel der Site-Generierung ist die Homepage des php-maven Projekts, die mit Maven erzeugt wurde.
Innerhalb der POM können verschiedene Angaben zu wichtigen Projektinformationen gemacht werden, die über eine Projektseite publiziert werden können. Typische Informationen sind unter anderem der Projektname mit einer Kurzbeschreibung, dem Gründungsjahr und der Lizenz des Artefakts. Neben diesen allgemeinen Informationen können auch die URLs zu CI-Servern, Sourcecode-Repositories, Mailing-Listen und beteiligten Personen angegeben werden. Die notwendigen Einträge der POM zeigt Listing 1.
<licenses><license><name>BSD 3-Clause</name><url>http://www.opensource.org/licenses/BSD-3-Clause/</url></license></licenses><name>CMS</name><description> A Collection of diffrent Modules for a CMS.</description><url>https://elmar-dott.com</url><inceptionYear>2012</inceptionYear><scm><url>https://git.elmar-dott.com</url><connection>https://git.elmar-dott.com</connection><developerConnection>https://git.elmar-dott.com</developerConnection></scm><issueManagement><system>Redmine</system><url>https://issues.elmar-dott.com/</url></issueManagement><ciManagement><system>Jenkins</system><url>http://localhost/jenkins</url></ciManagement><developers><developer><name>Elmar Dott</name><id>ed</id><email>ed@elmar-dott.com</email><roles><role>Release-Management</role></roles><organization>Elmar Dott Consulting</organization><organizationUrl>https://elmar-dott.com</organizationUrl><timezone>+1</timezone></developer></developers>
Um der Seite statische Inhalte zuzufügen, stehen unterschiedliche Mechanismen zur Auswahl. Grundlegend ist das Verzeichnis site unterhalb von src im Projektverzeichnis anzulegen, in dem unter anderem auch der Site-Deskriptor hinterlegt wird. Über den Site-Deskriptor site.xml werden unter anderem die Navigation zusammengebaut und zusätzliche Inhalte hinzugefügt. Es können drei unterschiedliche Content-Typen erzeugt werden: APT (Almost Plain Text) ist ein an Wiki Style angelehntes Format, während fml eine FAQ-Struktur erzeugt und überwiegend in Maven-1-Projekten zum Einsatz kam. Am verbreitetesten ist xDoc, ein XML-basiertes Format, um Inhalte zu erstellen.
Um der Seite verschiedenste Reports hinzuzufügen, ist das Site-Plug-in entsprechend zu konfigurieren. Der übliche Weg über den Abschnitt <reports> ist mittlerweile als deprecated gekennzeichnet und sollte nicht weiter verwendet werden. Um nicht benötigte Reports auszusparen, werden diese in der Konfiguration des <reportSets> weggelassen. Auf der Maven-Plugin-Seite finden sich noch weitere Plug-ins zu Reports, beispielsweise das Checkstyle-Plug-in, um den Code auf die Einhaltung festgelegter Style-Guides zu prüfen.
Wer bereits einmal in die Verlegenheit gekommen ist eine im Produktivzustand arbeitende PHP-Webapplikation zu aktualisieren, wird mir sicherlich beipflichten, das diese Arbeit äußerst ungern gemacht wird. Eine andere Unschönheit ergibt sich daraus, wenn ein solches System für die Entwicklung eines neuen Webauftritts beispielsweise lokal installiert wird. Nach getaner Arbeit sind dann verschiedene Hürden zu meistern, um die Anwendung über ein QS-System auf dem Live-Server lauffähig zu bekommen. Viele Probleme lassen sich bereits während der Entwicklungsphase durch etwas Planung und eine saubere Architektur vermeiden. Gerade bei Webanwendungen kann durch eine effiziente Modularisierung in Kombination mit Maven ein erheblicher Mehrwert erzielt werden.
Ziel dieses Teils der Artikelserie ist es nicht, Migrationswege für bereits bewährte Webapplikationen wie beispielsweise Magento, Media-Wiki und Jomoola nach Maven aufzuzeigen. Ein solches Vorhaben sollte aus verschiedenen Gründen reiflich überlegt werden und ist eher etwas für erfahrene Entwicklungsteams. Für eine erfolgreiche Migration ist tiefgreifendes Systemwissen unbedingt notwendig.
Gezeigt wird, wie mit PHP und Maven moderne und zukunftssichere Webanwendungen erstellt werden können. Die Basis dazu bilden die bereits vorgestellten Library-Artefakte, die nun zu einer gesamten Anwendung orchestriert werden. Etablierte Applikationen wie Magento, um nur einen willkürlich gewählten Vertreter zu nennen, sind weitaus älter als die vorgestellten OOP-Eigenschaften, die durch PHP 5.3 eingeführt wurden. Deswegen ist auch kein direkter Architekturvergleich möglich.
Die Segel in Richtung Zukunft
Die Vision in der Software-Entwicklung besteht vor allem darin, einmal entwickelte Module wiederverwenden zu können. Im PHP-Maven-Projekt ist das erklärte Ziel, ein umfangreiches Repository an freien und kommerziellen Artefakten im Lauf der Zeit anzusammeln und zur Verfügung zu stellen. Um Namenskonflikten aus dem Weg zu gehen, ist die Verwendung von Namespaces in Library-Projekten unumgänglich. Wichtige Designregeln sollten zwingend eingehalten werden, wofür die folgende Checkliste herangezogen werden kann:
echo und print sind innerhalb des Produktivcodes absolut tabu.
Die Entwicklung erfolgt rein objektorientiert (OOP).
Namespaces sind zu verwenden.
Eine Klasse pro Datei, wobei Klasse und Dateinamen identisch sind (korrespondieren).
Kein Modul darf direkt auf eine Datenbanktabelle eines anderen Artefakts zugreifen; es sind nur API-Aufrufe gestattet.
Content wird über Datenbanktabellen persistiert.
Die Konfiguration erfolgt über XML- oder INI-Dateien.
Diese Liste der aufgezählten Punkte stellt eine Mindestanforderung für Artefakte dar, die darauf abzielen, ihre Funktionalität möglichst vielen Projekten über einen langen Release-Zeitraum zur Verfügung zu stellen. Die Reihenfolge ist keine Priorisierung. Ein klarer Stil der Codierung sollet stringent eingehalten werden. Beachtet man diese Punkte nicht, kann sich das negativ auf den Entwicklungsprozess auswirken.
Die Problematik der Namespaces wurde bereits erläutert. Die Forderung, dem OOP-Paradigma zu folgen, begründet ihren Ursprung vor allem in der Kapselung der Funktionalitäten und der guten Strukturierung des Codes. Dass der Dateiname mit der Klasse zu korrespondieren hat, dient ebenfalls der besseren Übersicht und ermöglicht das Verwenden von Auto-Class-Loadern. In aller Regel werden fertige Artefakte durch eine übergeordnete Anwendung aufgerufen. Erzeugt ein Artefakt eigenständig sichtbare Systemausgaben in der Anwendung, ist dies ein ernstes Problem. Fehler oder Debug-Ausgaben sind aus diesem Grund ausschließlich über ein Logging-Verfahren zu behandeln. Ein sehr wichtiger Punkt im Hinblick auf die Wartbarkeit einer Applikation ist die Forderung nach Zugriffen auf Datenbanktabellen. Sicherlich mag im ersten Moment ein SQL-Statement attraktiver wirken als ein API-Aufruf. Immerhin attestiert es dem Entwickler einen tiefen Einblick in das vorhandene System. Dummerweise offenbart ein solches Vorgehen nicht die Brillanz des Akteurs, sondern dessen mangelnde Teamfähigkeit.
Ein weiterer Aspekt ist das Persistieren von Daten. Die Faustregel zur Entscheidung, wie Daten langfristig zu speichern sind, ist, dass alle Einstellungen, die das Verhalten eines Systems beeinflussen, in Textdateien abgelegt werden sollten. Durch Nutzer erzeugte Inhalte wie Texte gehören in eine Datenbank. Typische Konfigurationseinstellungen sind Datenbankparameter, da sie sich je nach System unterscheiden. Solche Dinge in einer Datenbank abzulegen erschwert den Aufwand des Deployments erheblich. Content hingegen hat keinen direkten Einfluss auf die Applikation und muss daher nicht in die Entwicklungssysteme synchronisiert werden. Im Gegenteil, dieser Zustand wäre ein erhebliches Sicherheitsrisiko. Ein Beispiel wären Accountdaten mit Adresse und Bankverbindung der Nutzer eines Webshops. Diese Information ist nur dem Betreiber zugedacht und nicht der Entwicklungsabteilung der Applikation.
Strukturarbeiten
Nachdem nun die Voraussetzungen für optimales Artefakt-Design bekannt sind, ist es an der Zeit, diese durch eine Webanwendung zu einem Gesamtwerk zu vereinen. Auch wenn es auf den ersten Blick trivial erscheint: Ein geschickt gewähltes Verzeichnislayout ist bereits die halbe Miete. Bild 1 enthält eine empfohlene Verzeichnisstruktur für Webprojekte mit den wohlbekannten Elementen. Einzige Ausnahme bildet hier der Ordner PHP-INF mit sämtlichen geschützten Inhalten, die für Außenstehende nicht einsehbar sein dürfen. Das Vorbild dieses Verzeichnisses ist Java-Webprojekten entnommen. Um das PHP-INF Verzeichnis vor unerwünschten Blicken verborgen zu halten, bietet sich eine .htaccess Datei in Kombination mit einer robots.txt an, die sämtliche Suchmaschinen aussperrt, um nur einige Schutzmechanismen aufzuzeigen.
Von besonderem Interesse sind die Dateien des Unterverzeichnisses libs. Wie diese PHP-Archive erzeugt werden, wurde im vorangegangenen Teil dieser Serie beschrieben. Im Kontext der Webanwendung sind diese Artefakte einfache Dependencies, die durch Maven verwaltet werden und über die Bootstrap-Datei index.php eingebunden sind. Auf diese Weise entsteht im Lauf der Zeit ein Baukastenprinzip, ähnlich einem Komponenten-Framework.
Im Gegensatz zum vorgestellten Library-Projekt befinden sich die Sourcen nun im Ordner resources. Der Grund dafür ist sehr schnell aufgezeigt. Maven kopiert aus diesem Verzeichnis die Dateien in der gleichen Hierarchie in das target Verzeichnis. Ein besonders hilfreiches Feature ist, dass Maven im resources Verzeichnis Filter anwenden kann, die es ermöglichen, Texte zu ersetzen. Dazu ist lediglich über den Build-Lifecycle das Filtering in der POM zu aktivieren:
Diese Eigenschaft ist besonders wertvoll für das Deployment. In den Konfigurationsdateien der Anwendung können so Systemeigenschaften in Platzhalter ausgelagert werden. So erklärt sich auch die strikte Forderung, Systeminformationen in Textdateien vorzuhalten. Es besteht natürlich auch die Option, in SQL-Dateien eine Textersetzung vorzunehmen, um Konfigurationen vorzuhalten. Man sollte sich aber bewusst sein, dass Datenbanktabellen, die im schlimmsten Fall in einer Spalte Konfigurationen vorhalten, kaum zum Verständnis des Systems beitragen. Besonders aus Sicht der Wartbarkeit bietet eine Konfigurationsdatei mehr Flexibilität als SQL-Statements. Die Eigenheit, alles möglichst über Datenbanktabellen abzuspeichern, hat eine eher einfache Ursache. Eine Konfigurationsdatei im Filesystem muss durch verschiedene Mechanismen vor unbefugtem Zugriff geschützt werden. Datenbanktabellen bieten von Hause aus mehr Sicherheit. Ähnlich verhält es sich bei den bekannten config.php Files.
Um Texte ersetzen zu können, werden sogenannte Profile benötigt, die in dem vorgestellten Beispiel über die POM vorgehalten werden. Die verschiedenen Profile werden über eine ID unterschieden.
Ein möglicher Weg, um ein Profil zu aktivieren, ist das <activeByDefault> -Tag. Es gibt natürlich auch noch viele andere Wege, die auf der Manual-Page beschrieben werden.
PHP-CLI
Damit Maven seine volle Kraft ausschöpfen kann, ist es notwendig, das Command Line Interface (CLI) für PHP in der Konsole zu aktivieren.
Mit dem CLI ist es möglich, PHP-Skripts ohne Webbrowser direkt auf der Kommandozeile auszuführen. Diese Funktion wird beispielsweise benötigt, um aus Maven heraus die Sourcecode-Dokumentation über den php-Documentor anzustoßen. Sobald der Pfad zum Verzeichnis der php.exe in die PATH-Variable aufgenommen wurde, können PHP-Skripts über die Konsole ausgeführt werden. Der Erfolg einer Installation lässt sich durch die Anweisung php –v rasch überprüfen. Im Erfolgsfall wird sie mit der Ausgabe der installierten PHP-Version quittiert.
Packungsinhalte
Nachdem die Projektstruktur von Webapplikationen mit ihren Besonderheiten vorgestellt worden ist, ist es nun an der Zeit, einige Details über die POM zu erwähnen. Um die Vielseitigkeit von Maven zu demonstrieren, wird der Packagetyp rar gewählt. Durch etwas Zauberei wird allerdings keine RAR-Datei, sondern eine ZIP-Datei ausgeliefert. Der Grund für diese Entscheidung: Diese Webanwendung ist ein individuelles Projekt und soll nicht innerhalb anderer Projekte verwendet werden. Daher ist es nicht notwendig, das Artefakt in einem Repository vorzuhalten. Aus dieser Tatsache ergibt sich auch das verify.
Der Auszug der POM zeigt unter anderem auch, wie das Library-Projekt als Dependency eingebunden wird. Der Scope weist das Artefakt für die Verwendung zur Laufzeit aus. Damit die entsprechenden Dateien im target-Verzeichnis vollständig zu einer ZIP gepackt werden können, sind innerhalb des <build> Tags noch einige Plug-ins zu konfigurieren.
Eine zentrale Rolle spielt das antrun Plug-in. Um in Maven in Archiven zusätzlichen Inhalt einzufügen, sind Assemblies vorgesehen. Wesentlich einfacher ist der Weg über ANT. Das antrun Plug-in ermöglicht das Ausführen von ANT-Tasks.
Die Konfiguration des Plug-ins ist weitgehend selbsterklärend. Innerhalb von <configuration> können verschiedene Task definiert werden. Eine ausführliche Übersicht bietet das User-Manual von ANT.
Elternteile
In den POMs der Library-Artefakte ist der Eintrag zu finden, der auf eine parent-pom für PHP-Maven-Projekte verweist. Dieses Konstrukt bedeutet, dass dem aktuellen Projekt noch ein Projekt übergeordnet ist. Grundsätzlich können Projekte verschiedenster Art beliebig tief verschachtelt werden. Damit das gesamte Konstrukt aber auch überschaubar bleibt, sollte vorher reiflich überlegt werden, wie feingranular ein Projekt aufgebaut werden muss. Um ein Multiprojekt zu erzeugen, muss lediglich die -POM angegeben werden, und über den Eintrag kann auf die untergeord- neten Module verwiesen werden:
Der Vorteil des Multiprojekts modules ist, dass die gesamte Konfiguration für die Unterprojekte in der übergeordneten POM erfolgt. Es werden nur noch die individuellen Konfigurationen in den Unterprojekten ergänzt:
Wie an der POM des Validators zu sehen ist, ist die Konfiguration erfreulich kurz. Die Effizienz ergibt sich, sobald mehr als ein Modul im gleichen Kontext erzeugt wird. Die Parent-POM stellt sicher, dass für alle Teilprojekte dieselben Dependencies verfügbar sind. So kann verhindert werden, dass beispielsweise Modul A für die XML-Verarbeitung ein anderes Artefakt verwendet als Modul B. Dies ist ein wichtiger Aspekt für die Qualität von Software.
Ausblick
Nachdem Sie nun viele Details zu den Möglichkeiten von Maven kennengelernt haben, stellt der nächste und abschließende Teil dieser Serie das Eclipse-Plug-in für Maven for PHP vor und zeigt unter anderem, wie Webseiten und Reports über Maven generiert werden.
Der erste Teil der Serie hat gezeigt, dass Maven den Paradigmen DRY und COC folgt. Aus diesem Grund sollte beim Anlegen eines Projekts die vorgegebene Verzeichnisstruktur eingehalten werden. Es ist durchaus möglich, von dieser Empfehlung abzuweichen, was aber zur Folge hat, dass der Konfigurationsaufwand in der pom.xml erheblich anwächst und sich schnell Fehler einschleichen können. Bild 1 stellt eine einfache Ordnerstruktur für ein typisches Maven-Projekt dar.
Die beschriebene Struktur ist bis auf wenige Abweichungen für sämtliche Maven-Projekte identisch. Der wichtigste Teil ist die pom.xml im Wurzelverzeichnis des Projekts. Das optionale Verzeichnis site enthält alle notwendigen Dateien, um eine Projekt-Homepage durch Maven generieren zu lassen. In src vermuten Sie zu Recht die verschiedensten Quelltextdateien. Im Ordner test befinden sich sämtliche Testdateien. Die resources-Verzeichnisse sind optional und besitzen eine besondere Funktion: Dort werden vor allem Konfigurationsdateien abgelegt, in denen Platzhalter zur Textersetzung eingebunden werden können. Um die Zusammenhänge schneller zu erkennen, sollten Sie einen Blick in die Konfigurationsdatei pom.xml werfen.
Project Object Model
Das Project Object Model (POM) bildet die zentrale Steuereinheit für Maven und enthält alle nötigen Informationen. Eine vollständige Übersicht der Konfigurationsmöglichkeiten kann auf der Maven-Projektwebseite nachgeschlagen werden. Beginnen wir zuerst mit den wichtigsten Einträgen:
Diese vier Zeilen sind der essenzielle Bestandteil einer jeden POM. Nun wird auch ersichtlich, was es mit den Platzhaltern $groupID und $artifactID in der Projektstruktur auf sich hat. Die artifactId ist der Projektname, dem eine Version zugeordnet wird. Bei der groupId handelt es sich um die Domain des Projekts.
Diese Informationen benötigt Maven, um die Artefakte im Dependency-Management organisieren zu können. Daraus ergibt sich beim Anlegen eigener Projekte die Forderung, dass die Kombination aus Domäne, Projektnamen und Version nicht mehrfach vergeben werden darf, da sonst vorhandene Artefakte im lokalen Repository ohne Rückfrage sofort überschrieben werden. Da Maven für Java-Projekte konzipiert wurde, nutzte es auch den in Java vorhandenen Mechanismus der Packages. Das bedeutet für den Wert org.phpmaven in groupId, dass Maven den Punkt als Trennzeichen interpretiert und erst org und darunter phpmaven als Verzeichnis erzeugt. Auf diese Weise können Sie Ihre Artefakte im lokalen Repository jederzeit aufspüren.
Für Java-Projekte ist es notwendig, anhand des Package-Namens, der sich aus groupId und artifactId zusammensetzt, eine Ordnerhierarchie zu erzeugen. In PHP-Projekten ist das Anlegen einer solchen Struktur nicht zwingend notwendig. Mit Blick auf künftige Mehrfachverwendung von Artefakten in den verschiedenen eigenen Projekten ist die Verwendung von Namespaces unumgänglich. Das Risiko von Namenskonflikten zwischen den Artefakten steigt mit der Anzahl der verfügbareren Artefakte.
Der Eintrag php weist Maven an, aus den Source-Files ein Phar-Archiv zu erzeugen. Es gibt neben php noch weitere Package-Typen, etwa zip und pom. Der Package-Typ pom erlaubt die Verwendung von Multi-Projekten, auf die später noch eingegangen wird. Listing 1 zeigt eine vollständige POM für ein einfaches PHP-Library-Projekt, das Sie als Abhängigkeit in anderen Projekten nutzen können. Dependencies werden in der POM im Bereich eingetragen. Im Beispiel ist das Test-Framework PHPUnit eingebunden. Die Angabe teilt Maven mit, dass es sich bei diesem Artefakt um ein PHP-Archiv handelt. Ohne diese Konfiguration würde Maven ein Java-Archiv (JAR) erwarten. Der Scope einer Dependency konfiguriert die Sichtbarkeit des Artefakts im Build Lifecycle. Es gibt vier unterschiedliche Scopes:
compile: Das Artefakt ist in allen Phasen verfügbar (Default).
provide: Das Artefakt ist nur bis zur compile-Phase sichtbar und wird nicht mit deployed. Dieser Scope ist vor allem für Java-Projekte wichtig, um die Ressourcen korrekt zu verlinken.
runtime: Diesen Scope verwenden Dependencies, die nur zur Laufzeit benötigt werden, was für PHP-Projekte die Regel darstellt. Artefakte, die mit runtime gekennzeichnet sind, werden mit der Anwendung zusammen deployed.
test: Abhängigkeiten, die mit diesem Scope konfiguriert sind, werden nicht mit deployed und sind nur für die test-Phasen des Build-Lifecycles sichtbar.
Nachdem Sie nun eine Projektstruktur und die dazugehörige POM haben, wird es Zeit, Maven in Aktion zu erleben. Die Idee ist, eine Bibliothek zu erzeugen, die Benutzereingaben validiert. Dieses Artefakt kann dann später von Ihnen dahingehend erweitert werden, in Ihren Projekten an verschiedensten Stellen Benutzereingaben auf Gültigkeit zu überprüfen.
Mögliche Erweiterungen könnten etwa Validierungen von ISBN- und IBAN-Nummern sein. Um ohne Verzögerung zu beginnen, können Sie das fertige Projekt von der Website herunterladen und in einer aktuellen IDE Ihrer Wahl öffnen.
Das Artefakt besteht aus der Klasse Validator mit den beiden Methoden makeSecure() und validate(). Die Methode makeSecure() soll HTML-Tags escapen und Slashes sowie Backslashes aus dem übergebenen String entfernen. validate() prüft eine Eingabe gegen einen regulären Ausdruck auf Gültigkeit. In der Klasse sind bereits einige RegEx als Konstanten definiert. Damit haben wir schon alles, um erste Resultate zu sehen.
Validierungen
Öffnen Sie eine beliebige Konsole und navigieren Sie in das Projektverzeichnis zur POM. Nun müssen sie lediglich mvn package eingeben. Diese Anweisung bewirkt, dass Maven den Build Lifecycle bis zur Phase package abarbeitet. Die nachfolgenden Phasen install und deploy werden nicht aufgerufen. Die Phase install kopiert das erzeugte Artefakt direkt in das lokale Repository und deploy würde zusätzlich das Artefakt in einem Remote-Repository ablegen. Für den Moment genügt es uns, das Phar-Archiv erzeugt zu haben.
Wegen des POM-Eintrags install unterhalb von <build> genügt es, lediglich mvn install in der Konsole zu schreiben, um das erzeugte Artefakt ins lokale Repository zu kopieren. Nachdem mvn package ausgeführt wurde, hat Maven im Projektverzeichnis einen temporären Ordner namens target erzeugt und quittiert die Ausgabe mit BUILD SUCCESS. In dem neu angelegten Verzeichnis sind sämtliche generierten Dateien abgelegt, unter anderem auch das erwünschte Phar-Archiv.
Um negative Synergien zu vermeiden, sollte das target-Verzeichnis vor einem jedem Build gelöscht werden. Das erledigt die Anweisung mvn clean.
Das erzeugte Phar-Archiv lässt sich mit den folgenden Zeilen in eine Applikation einbinden:
require_once 'phar://validator-1.0-SNAPSHOT.phar/index.php';use de\banaalo\validator\Validator as Validator;$validator = new Validator();$input = 12345;echo $validator->validate($validator->NUMBER, $input);
Der Trick besteht darin, sämtliche Klassen des Archivs in der Datei src/main/php/index.php mittels include bekannt zu machen. Bei dieser Herangehensweise muss lediglich die index.php wie in der ersten Zeile des Listings geladen werden. Anschließend ist noch der Namespace aufzulösen und dann können die Klassen des Artefakts wie gewohnt verwendet werden.
Testgetriebene Entwicklung
Dank des Extreme Programming (XP) hat das Testen von Sourcecode mittlerweile einen sehr zentralen Stellenwert im Software-Entwicklungsprozess erhalten. Implementierte Funktionalität wird nicht erst nach Beendigung der Entwicklung auf Korrektheit hin überprüft, sondern schon während der Entwicklungsphase. Eine etablierte Form des Testens sind Unit-Tests, wofür das Framework PHPUnit von Sebastian Bergmann als Dependency in den Maven-Build-Lifecycle eingebunden ist. Die aktuell verwendete Version von PHPUnit ist 3.6.10. Ein ausführliche Übersicht zu PHPUnit bietet das Manual des Frameworks.
Sämtliche Testfälle sind im Verzeichnis test/php abzulegen. Wenn eine Verzeichnisstruktur für die Sourcen erzeugt wurde, sollte diese ebenfalls für die Testfälle übernommen werden. Eine weitere Konvention ist, die Testklassen analog der zu testenden Klassen zu benennen und das Postfix test anzufügen.
Zur Klasse Validator existiert die korrespon-ierende Klasse ValidatorTest, die von PHPUnit_Framework_TestCase abgeleitet ist. Um später in der Test-Auswertung bei Fehlern das betroffene Fragment schneller identifizieren zu können, sollten die Methoden sprechende Namen haben. Im vorgestellten Beispielprojekt wird die Validierung von Zahlen durch den Validator getestet. Dazu existiert die Methode testNumberValidation(). Um Klassen testen zu können, sollte schon während der Implementierung darauf geachtet werden, dass nur ein Einstiegspunkt und ein definierter Ausstiegspunkt vorhanden ist. Mehr als das Erstellen der Testfälle und das Einbinden von PHPUnit als Abhängigkeit ist nicht notwendig. Beim Ausführen von Maven werden nun jedes Mal alle Testfälle abgearbeitet. Falls ein Test fehlschlägt, wird der Build mit einer Fehlermeldung abgebrochen.
API-Dokumentation auf Knopfdruck
Ein weiterer wichtiger Aspekt in der SoftwareEntwicklung ist das Erzeugen einer aussagekräftigen API-Dokumentation. Für diese Aufgabe ist in Maven der Site-Lifecycle vorgesehen. Um den phpDocumentor dem Site-Lifecycle bekannt zu machen, muss die Konfiguration des site-Plug-ins überschrieben werden. In der Beispiel-POM ist dies bereits geschehen und deswegen muss die POM nicht weiter angepasst werden. Wie auch bei PHPUnit ist es nicht notwendig, das Tool phpDocumentor auf dem System zu installieren. Auf der Homepage des php Documentors ist das Werkzeug gut dokumentiert. Auf der Webseite ist unter anderem eine Übersicht der möglichen Annotationen zu finden. Um die Dokumentation zu erzeugen, muss der Site-Lifecycle mit der Anweisung mvn site ausgeführt werden.
Wie alle anderen durch Maven erzeugten Dateien wird auch die fertige API-Dokumentation im target-Verzeichnis abgelegt.
Jedes Mal aufs Neue von Hand eine Projektstruktur anzulegen ist mühsam. Damit das Erzeugen neuer Projekte automatisiert geschehen kann, bietet Maven den Mechanismus der Archetypen. Ein Archetyp erzeugt eine vorgegebene Verzeichnisstruktur und die dazugehörige POM. Für PHP existieren derzeit drei verschiedene Archetypen: library, web und zend, die im Lauf der Zeit noch erweitert werden. Der nachfolgende Code-Ausschnitt zeigt die benötigte Anweisung, um einen Archetyp auszuführen:
Falls Sie aus einem bereits bestehendem Projekt einen Archetyp erzeugen wollen, können Sie mvn archetype:create-from-project ausführen. Es kann auch vorkommen, dass anschließend der generierte Archtyp von Maven nicht gefunden wird. Der Grund ist in der Datei archetypecatalog.xml zu suchen. Um den neuen Archetyp in den Katalog aufzunehmen, ist die Anweisung mvn archetype:crawl auszuführen. Ein manuelles Editieren dieser Datei ist nicht notwendig.
Fazit
Library-Projekte sind Artefakte, die Funktionalitäten kapseln und diese Funktionalitäten in anderen Projektformen als Abhängigkeit zur Verfügung stellen. Im nächsten Teil der Serie wird gezeigt, wie Homepage-Projekte mit Maven verwaltet werden können, die wiederum Artefakte einbinden. In diesem Zusammenhang wird auch auf Multi-Projekte und deren Verwendung eingegangen. Sie erfahren auch, wie Sie erzeugte Artefakte für andere Entwickler in einem Remote-Repository verfügbar machen.
[EN] We use cookies to improve your experience on our site. By using our site, you consent to cookies.
[DE] Wir verwenden Cookies, um Ihre Erfahrungen auf unserer Website zu verbessern. Durch die Nutzung unserer Website stimmen Sie Cookies zu.
This website uses cookies
Websites store cookies to enhance functionality and personalise your experience. You can manage your preferences, but blocking some cookies may impact site performance and services.
Essential cookies enable basic functions and are necessary for the proper function of the website.
Name
Description
Duration
Cookie Preferences
This cookie is used to store the user's cookie consent preferences.
30 days
These cookies are needed for adding comments on this website.
Name
Description
Duration
comment_author
Used to track the user across multiple sessions.
Session
comment_author_email
Used to track the user across multiple sessions.
Session
comment_author_url
Used to track the user across multiple sessions.
Session
These cookies are used for managing login functionality on this website.
Name
Description
Duration
wordpress_logged_in
Used to store logged-in users.
Persistent
wordpress_sec
Used to track the user across multiple sessions.
15 days
wordpress_test_cookie
Used to determine if cookies are enabled.
Session
Statistics cookies collect information anonymously. This information helps us understand how visitors use our website.
Matomo is an open-source web analytics platform that provides detailed insights into website traffic and user behavior.