Featureitis

Man muss nicht gleich Softwareentwickler sein, um ein gutes Anwendungsprogramm erkennen zu können. Doch aus eigener Erfahrung ist es mir oft passiert, dass Programme, die zu Beginn vielversprechend und innovativ waren, ab einer ‚gewissen‘ Nutzerzahl zu unhandlichen Boliden mutiert sind. Da ich diese Beobachtung nun schon einige Jahrzehnte regelmäßig aufs Neue mache, habe ich mich gefragt, woran das wohl liegen kann.

Das Phänomen, dass Softwareprogramme oder Lösungen im Allgemeinen mit Details überladen werden, hat Brooks in seinem Klassiker ‚The Mythical Man-Month‘ als Featuritis bezeichnet. Wenn man überlegt, dass die Erstausgabe des Buches im Jahr 1975 erschienen ist, kann man wohl von einem lange bekannten Problem sprechen. Das wohl bekannteste Beispiel für Featuritis ist das Betriebssystem Windows von Microsoft. Natürlich gibt es noch unzählige andere Beispiele für Verschlimmbesserungen.

Windowsnutzer, die bereits Windows XP kannten und dann mit dem tollen Nachfolger Vista konfrontiert wurden, um dann mit Windows 7 wieder besänftigt zu werden, um mit 8 und 8.1 beinahe einen Herzinfarkt erlitten zu haben, sich zu Beginn von Windows 10 wieder beruhigen. Jedenfalls für kurze Zeit, bis der Updatezwang für schnelle Ernüchterung sorgte. Von Windows 11 ganz zu schweigen. Zu Windows hieß es einmal, jede zweite Version ist Schrott, die sollte man überspringen. Nun ja, das stimmt seit Windows 7 schon lange nicht mehr. Für mich war Windows 10 dann der ausschlaggebende Punkt, vollständig auf Microsoft zu verzichten, und ich habe mir wie viele andere auch ein neues Betriebssystem zugelegt. Einige sind zu Apple gewechselt, und wer sich die teure Hardware nicht leisten kann oder will, hat wie ich auf ein Linuxsystem gesetzt. Hier zeigt sich, wie Uneinsichtigkeit schnell zum Verlust signifikante Marktanteile führt. Da Microsoft aus diesen Entwicklungen keine Konsequenzen zieht, scheint dem Unternehmen dieser Umstand weniger wichtig zu sein. Andere Unternehmen wiederum kann so etwas schnell an den Rand der Existenz bringen, und darüber hinaus.

Eine Motivation, immer mehr Funktionen in eine bestehende Anwendung zu bringen, ist der sogenannte Produktlebenszyklus, der durch die BCG Matrix in Abbildung 1 dargestellt wird.

Mit der Einführung ist noch nicht sicher, ob das Produkt vom Markt akzeptiert wird. Wenn es die Nutzer annehmen, steigt es schnell zum Star auf und erreicht seine maximale Marktposition als Cash Cow. Sobald die Sättigung überschritten wurde, degradiert es zum Ladenhüter. Soweit, so gut. Leider herrscht im Management überwiegend die Idee, dass, wenn kein Wachstum zum vorherigen Quartal mehr erzeugt wird, die Sättigung bereits überschritten wurde. So kommt es zu der sinnbefreiten Annahme, den Nutzern müsste jedes Jahr eine aktualisierte Version des Produktes aufgedrängt werden. Die Motivation zu kaufen gelingt natürlich nur, wenn eine dickgefüllte Featureliste an Neuerungen auf die Verpackung gedruckt werden kann.

Da sinnvoll konzipierte Funktionen sich aber nicht wie am Fließband aus dem Ärmel schütteln lassen, kommt auch jedes Mal gleich ein Redesign der grafischen Benutzeroberfläche als Gratis-Schmankerl mit dazu. Schließlich hat man dann das Gefühl, man habe etwas völlig Neues, weil man erst wieder eine Eingewöhnung braucht, um die neue Platzierung alt bekannter Funktionen zu entdecken. Es ist ja nicht so, dass das Redesign in der Benutzung Wege verkürzen würde und die Produktivität erhöht. Die Zusammenstellung der Eingabemasken und Schaltflächen erscheint jedes Mal willkürlich zusammengewürfelt.

Aber keine Sorge, ich will nicht zum Updateboykott aufrufen, sondern einmal darüber sprechen, wie man es besser machen kann. Denn eines sei gewiss: Dank künstlicher Intelligenz wird sich der Markt für Softwareprodukte in wenigen Jahren massiv verändern. Ich erwarte nicht, dass komplexe und spezialisierte Anwendungsprogramme in absehbarer Zeit durch KI-Algorithmen produziert werden. Allerdings erwarte ich, dass in diesen Anwendungsprogrammen genügend KI generierte schlechte Codesequenzen, die der Entwickler nicht versteht, in die Codebasis eingebracht werden, was zu unstabilen Anwendungen führen wird. Diese Überlegung ist für mich ein Grund, wieder über saubere, handgemachte, leitungsfähige und verlässliche Software nachzudenken, denn ich bin mir sicher, dass dafür immer ein Markt bestehen bleiben wird.

Ich möchte einfach keinen Internetbrowser, der zu einer Kommunikationszentrale mutiert ist und neben dem eigentlichen Anzeigen von Internetseiten noch Chat, E-Mail, Kryptobezahlmethoden und was weiß ich noch alles enthält. Ich möchte, dass mein Browser schnell startet, wenn ich irgendetwas klicke, dann schnell reagiert und die Inhalte der Internetseiten korrekt und schnell darstellt. Sollte ich einmal den Wunsch haben, etwas anderes mit meinem Browser zu tun, wäre es nett, wenn ich dies aktiv durch ein Plug-in aktivieren kann.

Nun gibt es zu dieser gerade beschriebenen Problemstellung oft die Argumentation, dass man ja mit den vielen Funktionen einen breiten Nutzerkreis erreichen möchte. Gerade wenn eine Anwendung zu Beginn alle möglichen Optionen auch aktiv eingeschaltet hat, holt das schnell den unkundigen Benutzer ab, der dann nicht erst begreifen muss, wie sein Programm überhaupt funktioniert. Ich kann diese Überlegung durchaus nachvollziehen. Es ist auch völlig in Ordnung, wenn ein Hersteller sich ausschließlich auf unkundige Anwender konzentriert. Es gibt aber einen Mittelweg, der alle Nutzergruppen gleichmäßig berücksichtigt. Diese Lösung ist auch nicht neu und sehr gut bekannt, die sogenannten Produktlinien.

In der Vergangenheit haben Hersteller immer Zielgruppen wie Privatpersonen, Unternehmen und Experten definiert. Diesen Nutzergruppen wurden dann oft Produktbezeichnungen wie Home, Enterprise und Ultimate zugeordnet. Das führte dazu, dass jeder die Ultimate Version wollte. Das Phänomen nennt sich Fear Of Missing Out (FOMO), also etwas zu verpassen. Deswegen sind die Bezeichnungen der Produktgruppen und deren zugeordneten Funktionen psychologisch ungeschickt gewählt. Wie kann man das also besser machen?

Ein Experte konzentriert sich bei seiner Arbeit auf spezielle Basisfunktionen, mit denen er seine Aufgaben schnell und ohne Ablenkung erledigen möchte. Das impliziert für mich Begriffe wie Essentials, Pure oder Core als Produktline.

Wenn das Produkt dann noch im Unternehmen von mehreren Personen verwendet werden soll, benötigt dies oft zusätzliche Funktionen wie zum Beispiel ein externes Benutzermanagement, wie LDAP oder IAM. Diese spezialisierte Produktlinie assoziiert Begriffe wie Enterprise (verbrannt), Company, Business und so weiter.

Das zugemüllte Endergebnis, das eigentlich für NOOPS gedacht ist und alle möglichen Sachen bereits über die Installation aktiviert hat. Wenn den Leuten die Zeit, bis die Anwendung gestartet ist und sie reagiert, egal ist, dann nur zu. Immer in die Vollen. Rein, was rein geht! Hier eignen sich Bezeichnungen wie Ultimate, Full und Maximized Extended als Bezeichnung der Produktlinie. Wichtig ist nur, dass die Profis erkennen, dass es sich um die zugemüllte Variante handelt.

Wer nun geschickt mit diesen Produktlinien spielt und möglichst alle Funktionen über sogenannte Module bereitstellt, die nachinstallierbar sind, ermöglicht eine hohe Flexibilität auch im Expertenmodus, denen durchaus die eine oder andere Zusatzfunktion genehm ist.

Installiert man auf das Modulsystem zuvor noch ein Tracking, um festzustellen, wie professionelle Anwender ihre Version upgraden, dann hat man schon eine gute Idee, was in die neue Version von Essentials hinzugefügt werden könnte. Bei dem Tracking sollte man sich aber nicht auf die Downloads als Entscheidungskriterium stützen. Ich selbst probiere oft Dinge aus und lösche Erweiterungen auch schneller, als der Installationsprozess gedauert hat, wenn ich der Meinung bin, dass diese nutzlos sind.

Ich möchte zu der gerade beschriebenen Problematik ein kleines Beispiel geben, das aus dem DevOps Bereich stammt. Zum einen gibt es das bekannte GitLab, das ursprünglich einmal ein reines Code Repository-Hosting-Projekt gewesen ist. Darauf deutet auch der Name, bis heute. Eine Anwendung, die auf einem Server bereits 8 GB RAM in der Basis-Installation benötigt, um ein Git Repository für andere Entwickler erreichbar zu machen, ist für mich unbrauchbar, denn diese Software wurde über die Zeit zur EierlegendenWollmilchSau. Langsam, unflexibel und mit allem Kram zugemüllt, der über Speziallösungen besser umgesetzt wurde.

GitLab gegenüber steht eine andere Lösung namens SCM-Manager, die weniger bekannt ist und sich ausschließlich auf das Bereitstellen der Code Repositories konzentriert. Ich selbst nutze und empfehle den SCM-Manager, weil er mit der Basis-Installation extrem kompakt ist. Aber dennoch gibt es eine gigantische Funktionsvielfalt, die man über Plug-ins nachrüsten kann.

Für mich sind Lösungen, die eine All In One Solution bereitstellen wollen, eher suspekt. Das ist für mich immer gleich dem Motto: alles und nichts. Es gibt keine EierlegendeWollMilchSau oder wie man in Österreich zu sagen pflegt, keinen Wunderwuzzi!

Wenn ich Programme für meinen Arbeitsprozess auswähle, orientiere ich mich ausschließlich an deren Kernfunktionalität. Sind die Grundeigenschaften, die das Marketing verspricht, wirklich vorhanden und möglichst intuitiv nutzbar? Gibt es eine aussagekräftige Dokumentation, die über ein bloßes ‚Hallo Welt‘ hinausgeht? Konzentriert man sich darauf, die Kernfunktionen stets zu optimieren, und berücksichtigt neue innovative Konzepte? Das sind Fragen, die für mich relevant sind.

Gerade im kommerziellen Umfeld werden oft Programme eingesetzt, die nicht halten, was das Marketing verspricht. Man wählt nicht aus, was man tatsächlich für die Erledigung der Aufgaben benötigt, sondern Anwendungen, deren Beschreibung mit sogenannten Buzzwords vollgestopft ist. Deswegen glaube ich, dass Unternehmen, die sich wieder auf die Kernkompetenzen fokussieren und dazu hoch spezialisierte Anwendungen nutzen, die Gewinner von morgen sind.


Von Missmanagement und Alpha-Geeks

Als ich neulich das Buch „The Manager’s Path“ von Camille Fournier in die Hand bekam, war ich recht schnell an Tom DeMarco erinnert. Dieser hat den Klassiker „Peopleware“ geschrieben und Anfang 2000 das Buch „Adrenalin Junkies und Formular Junkies“ veröffentlicht. Eine Liste an Stereotypen, die man in Softwareprojekten antreffen kann, mit Hinweisen, wie man mit ihnen umgeht. Nach einigen Jahrzehnten im Geschäft kann ich jedes einzelne Wort aus eigener Erfahrung bestätigen. Und es ist auch heute noch immer ein Thema, denn Menschen machen nun einmal Projekte und wir alle haben so unsere Eigenheiten.

Damit Projekte erfolgreich verlaufen, müssen nicht nur technische Herausforderungen gemeistert werden. Auch zwischenmenschliche Beziehungen spielen eine wesentliche Rolle für deren Erfolg. Ein wichtiger Faktor in diesem Zusammenhang, der oft wenig Beachtung findet, ist die Projektleitung. Es gibt Regale voller hervorragender Literatur, wie man ein guter Manager werden kann. Das Problem ist leider, dass nur wenige, die diese Position besetzen, diese nicht ausfüllen und noch weniger Interesse besteht, die eigenen Fertigkeiten weiterzuentwickeln. Das Ergebnis von schlechtem Management sind aufgeriebene und gestresste Teams, extremer Druck im Tagesgeschäft und oft auch Verzug von Lieferterminen. Da braucht man sich auch nicht wundern, wenn dies Auswirkungen auf die Qualität des Produktes hat.

Einer der ersten Sprüche, den ich in meinem Berufsleben gelernt habe, war: Wer glaubt, dass ein Projektleiter Projekte leitet, der glaubt auch, dass ein Zitronefalter Zitronen faltet. Es scheint also eine sehr alte Weisheit zu sein. Was ist aber das wirkliche Problem bei schlechtem Management? Jeder, der eine Stelle für einen Manager zu besetzen hat, ist in der Pflicht, dessen Fertigkeiten und charakterliche Eignung auf Herz und Nieren zu prüfen. Hier lässt man sich schnell von inhaltslosen Floskeln und einer Liste großer Namen in der Branche in der Vita beeindrucken, ohne die tatsächliche Leistung zu hinterfragen. In meiner Erfahrung bin ich vornehmlich auf Projektleiter gestoßen, die oft nicht die notwendigen fachlichen Kenntnisse hatten, um wichtige Entscheidungen zu treffen. Nicht selten wurde ich in IT-Projekten von Managern mit den Worten „Ich bin kein Techniker, macht das unter euch aus.“, abgefertigt. Das ist natürlich fatal, wenn die Person, welche die Entscheidungen treffen soll, diese nicht treffen kann, weil das notwendige Wissen fehlt. Ein Manager im IT-Projekt muss natürlich nicht wissen, welcher Algorithmus schneller terminiert. Hierfür gibt es die Möglichkeit von Evaluierungen, als Grundlage von Entscheidungen. Aber ein Grundverständnis der Programmierung sollte vorhanden sein. Wer nicht weiß, was eine API ist und wieso Module, die später zu einer Software zusammengesetzt werden sollen, durch Versionskompatibilitäten nicht zusammenarbeiten, hat keine Berechtigung, sich als Entscheidungsträger aufzuspielen. Ein Grundverständnis über die Prozesse in der Softwareentwicklung und die verwendeten Programmierparadigmen ist auch für Projektleiter, die nicht am Code arbeiten, unumgänglich.

Ich plädiere daher dafür, dass man nicht nur die Entwickler, die man einstellt, auf ihre Fertigkeiten hin prüft, sondern auch die Manager, die in ein Unternehmen aufgenommen werden sollen. Für mich ist ein absolutes No Go bei der Auswahl meiner Projekte, ein externes Projektmanagement. Das führt in aller Regel nur zu Chaos und Frustration bei allen beteiligten Personen, weswegen ich solche Projekte ablehne. Manager, die nicht ins Unternehmen eingebunden sind und deren Leistung nach dem Erfolg von Projekten bewertet wird, liefern erfahrungsgemäß keine saubere Arbeit ab. Zudem können interne Manager, ebenso wie die Entwickler, durch Mentoring, Trainings und Workshops ihre Fertigkeiten entwickeln und weiter ausbauen. Das Ergebnis sind ein gesundes, entspanntes Arbeitsklima und erfolgreiche Projekte.

Der Titel dieses Artikels weist auf toxische Stereotypen im Projekteschäft hin. Ich bin mir sicher, jeder ist auf den ein oder anderen Stereotypen bereits im beruflichen Umfeld getroffen. Es wird viel diskutiert, wie man mit diesen Zeitgenossen umgehen soll. Ich möchte aber anmerken, dass kaum jemand als „Monster“ geboren wurde. Dass Menschen so sind, wie sie sind, ist das Resultat ihrer Erfahrungen. Lernt ein Kollege, dass er, wenn er gestresst ausschaut und immer hektisch wirkt, als guter Arbeiter wahrgenommen wird, perfektioniert er dieses Verhalten über die Zeit.

Camille Fournier hat es mit dem Begriff „The Alpha Geek“ sehr auf den Punkt gebracht. Jemand, der seine Rolle im Projekt unersetzlich gemacht hat und auf alles eine Antwort hat. Meist verächtlich auf die Kollegen herabschaut, aber nie eine Aufgabe wirklich ohne Nacharbeiten anderer sauber zu Ende bringen kann. Unrealistische Abschätzungen für umfangreiche Aufgaben sind ebenso typisch wie die Relativierung komplexer Sachverhalte. Natürlich ist das der Liebling aller Projektleiter, die sich wünschen, das ganze Team würde aus diesen „Alpha Geeks“ bestehen. Ich bin mir sehr sicher, wenn dieser Traum wahr werden könnte, es die optimale Strafe für die Projektleiter wäre, die solche Menschen erst möglich machen.

Damit man sich im eigenen Unternehmen keine „Alpha Geeks“ züchtet, ist es notwendig, keinen Personenkult zu etablieren und die persönlichen Favoriten gegenüber dem restlichen Team zu überhöhen und auf ein Podest zu stellen. Natürlich ist es auch unabdingbar, stets die Arbeitsergebnisse zu hinterfragen. Wer eine Aufgabe als erledigt markiert und diese Nacharbeiten erfordert, sollte diese Nacharbeiten stets erneut zugewiesen bekommen, bis das Ergebnis zufriedenstellend ist.

Ich persönlich habe die selbe Auffassung wie Tom DeMarco, was die Dynamiken eines Projektes betrifft. Die Produktivität kann man zwar über die Menge der erledigten Aufgaben bewerten, dennoch gibt es auch noch weitere Einflüsse, die eine wichtige Rolle spielen. So habe ich durch meine Erfahrung die Auffassung, dass man, wie bereits erwähnt, sehr viel Wert darauf legen sollte, dass Mitarbeiter die begonnenen Aufgaben sauber und vollständig lösen, bevor sie eine neue Aufgabe annehmen. Kollegen, die eine bestimmte Aufgabe „kleinreden“ und zu geringe, unrealistische Einschätzungen abgeben, genau diese Aufgabe übernehmen. Zudem gibt es auch Kollegen, die zwar einen recht geringen Output haben, dafür aber sehr viel für die Harmonie im Team beitragen.

Wenn ich über Menschen spreche, die ein gesundes Team formen, meine ich damit nicht jeden Tag Süßigkeiten hinzustellen. Es geht um die, die durchaus gute Fähigkeiten haben und diese als Mentor anderen Kollegen beibringen. Meist haben diese Personen einen guten Stand im Team und ihnen wird viel Vertrauen entgegengebracht, weswegen sie auch oft als Mediatoren bei Konflikten gute Ergebnisse erzielen. Es sind nicht die Menschen, die durch falsche Versprechen versuchen, everybodys Darling zu sein, sondern die, die zuhören und sich Zeit nehmen, eine Lösung zu finden. Sie sind oft das Mädchen für alles und haben nicht selten ein ruhiges, unscheinbares Auftreten. Da sie Lösungen haben und oft eine helfende Hand reichen, haben sie selbst eine mittelmäßige Bewertung ihrer Leistung in den typischen Prozessmetriken. Ein guter Manager erkennt diese Personen rasch, weil auf sie in aller Regel Verlass ist. Sie sind ausgeglichen und wirken wenig gestresst, weil sie mit Ruhe und Kontinuität vorgehen.

Natürlich kann man über die Stereotypen in einem Softwareprojekt noch viel mehr sagen, aber ich denke, die bereits getroffenen Ausführungen geben ein gutes Grundverständnis über das, was ich zum Ausdruck bringen möchte. Denn ein erfahrener Projektleiter kann viele der beschriebenen Probleme bereits während ihrer Entstehung wieder abstellen. Dazu gehören natürlich auch solides technisches Wissen und etwas Menschenkenntnis.

Es muss uns natürlich auch bewusst sein, dass erfahrene Projektleiter nicht einfach so da sind. Man muss sie genau wie die Mitglieder eines Teams entwickeln und fördern. Dazu gehört durchaus auch die Rotation durch alle technischen Abteilungen wie Entwicklung, Test und Betrieb. Dazu eignen sich Paradigmen wie Pairprogramming hervorragend. Denn es geht nicht darum, aus einem Manager einen Programmierer oder Tester zu machen, sondern ihm oder ihr ein Verständnis der täglichen Abläufe zu verschaffen. Das stärkt auch das Vertrauen in die Fertigkeiten des gesamten Teams, und Mentalitäten wie: Man müsse die faulen und unfähigen Programmierer kontrollieren und antreiben, damit sie einen Finger rühren, kommen gar nicht erst auf. In Projekten, die regelmäßig gute Qualität abliefern und ihre Termine einhalten, kommt selten der Wunsch auf, alle möglichen Prozessmetriken einzuführen.


Blockchain – eine Einführung

Das Konzept Blockchain ist grundlegender Bestandteil der verschiedenen Kryptobezahlmethoden wie Bitcoin und Ethereum. Was hat es aber mit der Technologie Blockchain auf sich und wozu kann man dieses Konzept noch anwenden? Grundlegend kann man sagen, dass Blockchain wie die Datenstruktur der rückwärtsverketteten Liste aufgebaut ist. Jedes Element der Liste zeigt auf den Vorgänger. Was macht die Blockchain aber nun so besonders?

Blockchain erweitert das Konzept der Liste um verschiedene Rahmenbedingungen. Eine dieser Rahmenbedingungen ist, sicherzustellen, dass kein Element der Liste verändert oder entfernt werden kann. Das lässt sich recht einfach bewerkstelligen. Hierzu verwendet man eine Hashfunktion. Wir codieren über einen Hashalgorithmus den Inhalt eines jeden Elements in der Liste zu einem Hash. Es gibt mittlerweile ein breites Angebot an Hashfunktionen, von denen ein aktueller Standard SHA-512 ist. In nahezu jeder Programmiersprache ist dieser Hashalgorithmus in der Standardbibliothek bereits implementiert und man kann ihn einfach verwenden. Im Konkreten bedeutet es, dass über die gesamten Daten eines Blockes der Hash SHA‑512 gebildet wird. Dieser Hash ist stets eineindeutig und kommt nicht noch einmal vor. Somit dient der Hash als Identifier (ID), um einen Block zu finden. Ein Eintrag in dem Block ist der Verweis auf seine Vorgänger. Dieser Verweis ist der Hashwert des Vorgängers, also seine ID. Bei der Implementierung einer Blockchain ist es essenziell, dass der Hashwert des Vorgängers Bestandteil der Berechnung des Hashwertes des aktuellen Blockes ist. Dieses Detail sorgt dafür, dass die in der Blockchain geänderten Elemente nur sehr aufwendig geändert werden können. Man muss sozusagen für das Element, das man manipulieren möchte, alle nachfolgenden Elemente ebenfalls ändern. Bei der umfangreichen Blockchain mit sehr vielen Blöcken bedeutet so ein Vorhaben einen enormen Rechenaufwand, der nur sehr schwer bis überhaupt nicht zu leisten ist.

Durch diese Verkettung erhalten wir eine lückenlose Transaktionshistorie. Dieser Umstand erklärt auch, weswegen Kryptobezahlmethoden nicht anonym sind. Auch wenn der Aufwand, einen Transaktionsteilnehmer eindeutig zu identifizieren, enorm werden kann. Nutzt dieser Transaktionsteilnehmer zudem noch verschiedene Verschleierungsmöglichkeiten mit unterschiedlichen und nicht durch weitere Transaktionen verknüpften Wallets, steigt der Aufwand exponentiell an.

Natürlich hat der gerade beschriebene Mechanismus noch erhebliche Schwachstellen. Denn Transaktionen, also das Hinzufügen neuer Blöcke, können erst als verifiziert und sicher eingestuft werden, wenn genügend Nachfolger in der Blockchain hinzugekommen sind, die sicherstellen, dass Änderungen wieder schwerer zu bewerkstelligen sind. Für Bitcoin und Co. gilt eine Transaktion als sicher, wenn fünf Nachfolgetransaktionen sind.

Damit es nun nicht nur eine Instanz gibt, die die Transaktionshistorie, also alle Blöcke der Blockchain, aufbewahrt, kommt ein dezentraler Ansatz ins Spiel. Es gibt also keinen zentralen Server, der als Vermittler agiert. Ein solcher zentraler Server könnte durch den Betreiber manipuliert werden. Man hätte so die Möglichkeit, mit genügend Rechenleistung auch sehr umfangreiche Blockchains neu aufzubauen. Im Kontext von Kryptowährungen spricht man hier von einer Reorganisation der Chain. Dies ist auch die Kritik an vielen Kryptowährungen. Außer Bitcoin existiert keine andere dezentrale und unabhängige Kryptowährung. Wenn die Blockchain mit allen ihren enthaltenen Elementen öffentlich gemacht wird und jeder Nutzer eine eigene Instanz dieser Blockchain lokal auf seinem Rechner besitzt und dort Elemente hinzufügen kann, die dann mit allen anderen Instanzen der Blockchain synchronisiert werden, haben wir einen dezentralen Ansatz.

Die Technologie zur dezentralen Kommunikation ohne einen Vermittler nennt sich Peer to Peer (P2P). P2P Netzwerke sind besonders in ihren Entstehungsphasen, also wenn nur wenige Teilnehmer im Netzwerk sind, schwach und angreifbar. Man könnte einfach mit sehr viel Rechenleistung eine große Anzahl von sogenannten Zomi Peers erstellen, die das Verhalten des Netzes beeinflussen. Gerade in Zeiten, in denen das Cloud-Computing mit AWS und der Google Cloud Platform als Anbieter, für vergleichsweise wenig Geld schier endlose Ressourcen bereitstellen kann, ist dies ein nicht zu unterschätzendes Problem. Besonders wenn es einen sehr hohen finanziellen Anreiz für Betrüger gibt, darf man diesen Punkt auf keinen Fall vernachlässigen.

Auch bei P2P gibt es verschiedene Konzepte, die miteinander konkurrieren. Um eine stabile und sichere Blockchain zu implementieren, ist es notwendig, nur auf Lösungen zurückzugreifen, die ohne unterstützende Backbone Server auskommen. Es soll vermieden werden, dass sich eine Master Chain etablieren kann. Daher müssen Fragen geklärt werden, wie sich die einzelnen Peers finden können und mit welchem Protokoll sie ihre Daten synchronisieren. Als Protokoll verstehen wir ein Regelwerk, also ein festes Schema, wie die Interaktion zwischen den Peers geregelt wird. Da bereits dieser Punkt sehr umfangreich ist, verweise ich zum Einstieg in das Thema auf meinen Vortrag 2022.

Eine weitere Eigenschaft von Blockchain‑Blöcken ist, dass sich diese problemlos und mit wenig Mühe auf Gültigkeit hin verifizieren lassen. Hierzu muss lediglich über die gesamten Inhalte eines Blocks der SHA-512 Hash erzeugt werden. Stimmt dieser mit der ID überein, ist der Block gültig. Aber auch zeitrelevante beziehungsweise zeitkritische Transaktionen, wie sie bei Bezahlsystemen relevant sind, lassen sich mit wenig Aufwand erstellen. Dazu werden auch keine komplexen Zeitserver als Vermittler benötigt. Jeder Block wird um einen Zeitstempel erweitert. Dieser Zeitstempel muss allerdings den Ort, an dem er erstellt wird, berücksichtigen, also die Zeitzone mit angeben. Um den Standort der Transaktionsteilnehmer zu verschleiern, können auch alle Uhrzeiten der verschiedenen Zeitzonen auf die aktuelle UTC 0 umgerechnet werden.

Um sicherzustellen, dass die Uhrzeit auch korrekt auf dem System eingestellt ist, kann man einen Zeitserver für die aktuelle Uhrzeit beim Start der Software abfragen und bei Abweichungen einen Hinweis zur Korrektur ausgeben.

Natürlich sind zeitkritische Transaktionen mit einer Reihe von Problemen behaftet. Es muss sichergestellt werden, dass eine Transaktion in einem festgelegten Zeitfenster durchgeführt wurde. Ein Problem, mit dem sich sogenannte Echtzeitsysteme auseinandersetzen müssen. Aber auch das Double Spending Problem muss verhindert werden. Also, dass derselbe Betrag zweimal an unterschiedliche Empfänger gesendet werden kann. Was in einem dezentralisierten Netzwerk die Bestätigung der Transaktion von mehreren Teilnehmern erfordert. Aber auch klassische Race Conditions können ein Problem darstellen. Race Conditions lassen sich durch die Anwendung des Immutable-Entwurfsmusters auf die Block-Elemente beherrschen.

Damit die Blockchain nun nicht durch Spam-Attacken gestört wird, benötigen wir eine Lösung, die das Erstellen eines einzelnen Blocks in der Masse teuer macht. Das erreichen wir, indem wir die Rechenleistung einbeziehen. Hierzu muss der Teilnehmer, der einen Block erstellt, ein Puzzle lösen, das eine ‚gewisse‘ Rechenzeit beansprucht. Wenn ein Spammer das Netzwerk mit vielen Blöcken fluten möchte, steigt seine Rechenleistung exorbitant an und es ist ihm unmöglich, in kurzer Zeit beliebig viele Blöcke zu erzeugen. Dieses kryptografische Puzzle nennt man Nonce, was für „number used only once“ steht. Der Mechanismus Nonce in der Blockchain wird auch oft als Proof of Work (POW) bezeichnet und dient bei Bitcoin zur Verifizierung der Blöcke durch die Miner.

Die Nonce ist eine (pseudo) zufällige Zahl, zu der ein Hash generiert werden muss. Dieser Hash muss dann ‚bestimmte‘ Kriterien erfüllen. Das können zum Beispiel zwei oder drei führende Nullen im Hash sein. Damit man nun keinen beliebigen Hash in den Block einfügt, wird die Zufallszahl, die das Rätsel löst, direkt abgespeichert. Eine bereits genutzte Nounce darf kein weiteres Mal verwendet werden, da sonst das Rätsel umgangen werden kann. Erzeugt man nun aus der Nonce den Hash, muss dieser die Vorgaben z. B. führende Nullen erfüllen, um akzeptiert zu werden.

Da je mehr Blöcke in einer Blockchain enthalten sind, es immer schwieriger wird, eine gültige Nonce zu finden, ist es notwendig, die Regeln für so eine Nonce zyklisch, beispielsweise alle 2048 Blöcke, zu verändern. Das bedeute aber auch, dass die Regeln für eine gültige Nonce ebenfalls den entsprechenden Blöcken zugeordnet werden müssen. Ein solches Regelwerk für die Nonce lässt sich problemlos über eine RegEx formulieren.

Mittlerweile haben wir auch eine beachtliche Menge an Regelwerk für eine Blockchain kennengelernt. Sodass es nun an der Zeit ist, sich ein wenig Gedanken über die Performance zu machen. Würden wir alle einzelnen Blöcke der Blockchain einfach in einer Liste abspeichern, würde uns recht bald der Arbeitsspeicher ausgehen. Jetzt könnte man die Blöcke auch in einer lokalen Datenbank speichern, was auch bei einer Embedded-Lösung wie SQLlite durchaus negative Auswirkungen auf die Geschwindigkeit der Blockchain haben würde. Eine einfache Lösung wäre hier, die Blockchain in gleichlange Teile zu zerlegen, sogenannte Chunks. Ein Chunk hätte sozusagen eine feste Länge von 2048 validen Blöcken und der erste Block eines neuen Chunk zeigt auf den letzten Block des vorhergehenden Chunk. In jedem Chunk kann man auch eine zentrale Regel für die Nonce hinterlegen und mögliche Metadaten wie beispielsweise Min- und Max-Zeitstempel abspeichern.

Wenn wir unseren aktuellen Stand des Blockchain-Regelwerks kurz rekapitulieren, kommen wir aktuell auf drei verschiedene Ebenen. Die größte Ebene ist die Blockchain selbst, welche grundlegende Metainformationen und Konfigurationen enthält. Solche Konfigurationen sind etwa der verwendete Hash Algorithmus. Die zweite Ebene stellen die sogenannten Chunks dar, die eine festgelegte Menge an Block-Elementen enthalten. Wie bereits erwähnt enthalten die Chunks auch Metadaten und Konfigurationen. Das kleinste Element der Blockchain ist der Block selbst, der aus einer ID, den beschriebenen Zusatzinformationen wie Zeitstempel und Nonce und dem Payload besteht. Der Payload ist eine allgemeine Bezeichnung für jedes beliebige Datenobjekt, das durch die Blockchain überprüfbar gemacht werden soll. Für Bitcoin und andere Kryptowährungen ist der Payload die Information, welcher Betrag von Wallet A (Quelle) an Wallet B (Ziel) transferiert wird.

Die Blockchain-Technologie eignet sich aber auch für viele andere Anwendungszenarien. So könnten beispielsweise die Hashwerte von Open-Source-Software Artefakten in einer Blockchain gespeichert werden. Damit könnte man auch Binärdateien aus unsicheren Quellen herunterladen und gegen die entsprechende Blockchain verifizieren. Das gleiche Prinzip wäre auf für die Signaturen von Antivirenprogrammen denkbar. Aber auch im behördlichen Umfeld könnten Anträge und andere Dokumente rechtssicher übermittelt werden. Die Blockchain würde hier als ‚Posteingangsstempel‘ funktionieren. Aber auch Buchhaltung inklusive aller Belege der Warenwirtschaft aus dem Einkauf und der verkauften Artikel und Dienstleistungen sind denkbare Szenarien.

Eine Erweiterung der Blockchain wäre je nach Anwendungsfall die eindeutige Signierung eines Blocks durch den Ersteller. Hierzu käme das klassische PKI Verfahren mit dem öffentlichen und privaten Schlüssel zum Einsatz. Der Unterzeichner speichert in Block seinen öffentlichen Schlüssel, erstellt mittels seines geheimen Schlüssels über den Payload eine Signatur, die als Signatur ebenfalls im Block mitgespeichert wird.

Bisher gibt es zwei frei verfügbare Implementierungen der Blockchain, BitcoinJ und für Ethereum Web3j. Natürlich ist es möglich, mit den gerade beschriebenen Prinzipien auch eine eigene allgemeingültige Blockchain-Implementierung zu erstellen. Hier liegen die Stolperfallen natürlich in den Details, von denen ich in diesem Artikel bereits einige angesprochen habe. Grundsätzlich ist Blockchain aber auch keine Raketentechnologie und für erfahrene Entwickler gut beherrschbar. Wer mit dem Gedanken spielt, sich an einer eigenen Implementierung zu versuchen, hat nun genügend Grundwissen, um sich mit dem notwendigen Detailwissen in den verschiedenen zum Einsatz kommenden Technologien tiefer vertraut zu machen.


PDF-Generierung mit TP-CORE

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.

<dependency>
    <groupId>io.github.together.modules</groupId>
    <artifactId>core</artifactId>
    <version>3.1.0</version>
</dependency>

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>
<table border="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>

<img src="path/to/myImage.png" />

<h2>Links</h2>
<p>here we try a simple <a href="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.

Map<String, String> properties = new HashMap<>();
properties.put("prop_01", "value 01");
properties.put("prop_02", "value 02");
properties.put("prop_03", "value 03");

TemplateRenderer templateEngine = new VelocityRenderer();
String directory = Constraints.SYSTEM_USER_HOME_DIR +/;
String htmlTemplate = templateEngine
                .loadContentByFileResource(directory, "template.vm", properties);

Der TemplateRenderer benötigt drei Argumente:

  • 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.

PdfRenderer pdf = new OpenPdfRenderer();
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.

PdfRenderer pdf = new OpenPdfRenderer();
PdfDocument original = pdf.loadDocument( new File("document.pdf") );
PdfDocument reduced = pdf.removePage(original, 1, 5);
pdf.writeDocument(reduced, "reduced.pdf");


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/.

RTFM – benutzbare Dokumentationen

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.

  1. Schreibe aus Sicht des Lesers.
  2. Vermeide unnötige Wiederholungen.
  3. Vermeide Mehrdeutigkeiten, wenn nötig Notation erläutern.
  4. Verwende Standards wie z. B. UML.
  5. Halte Begründungen (Warum) fest.
  6. Die Dokumentation ist aktuell zu halten, aber nie zu aktuell.
  7. Ü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.


Plattenspieler II

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.

ed@local:~$ df -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
udev           devtmpfs   32G     0   32G   0% /dev
tmpfs          tmpfs     6.3G  2.8M  6.3G   1% /run
/dev/nvme0n1p2 ext4      1.8T  122G  1.6T   8% /
tmpfs          tmpfs      32G  8.0K   32G   1% /dev/shm
efivarfs       efivarfs  196K  133K   59K  70% /sys/firmware/efi/efivars
tmpfs          tmpfs     5.0M   16K  5.0M   1% /run/lock
tmpfs          tmpfs     1.0M     0  1.0M   0% /run/credentials/systemd-journald.service
tmpfs          tmpfs      32G   20M   32G   1% /tmp
/dev/nvme0n1p1 vfat      975M  8.8M  966M   1% /boot/efi
tmpfs          tmpfs     6.3G  224K  6.3G   1% /run/user/1000

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.

ed@local:~$ sudo lsblk
NAME         MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
loop0          7:0    0     4K  1 loop /snap/bare/5
loop1          7:1    0  73.9M  1 loop /snap/core22/2139
loop2          7:2    0 516.2M  1 loop /snap/gnome-42-2204/226
loop3          7:3    0  91.7M  1 loop /snap/gtk-common-themes/1535
loop4          7:4    0  10.8M  1 loop /snap/snap-store/1270
loop5          7:5    0  50.9M  1 loop /snap/snapd/25577
loop6          7:6    0  73.9M  1 loop /snap/core22/2133
loop7          7:7    0  50.8M  1 loop /snap/snapd/25202
loop8          7:8    0   4.2G  0 loop 
└─veracrypt1 254:0    0   4.2G  0 dm   /media/veracrypt1
sda            8:0    1 119.1G  0 disk 
└─sda1         8:1    1 119.1G  0 part 
sr0           11:0    1  1024M  0 rom  
nvme0n1      259:0    0   1.9T  0 disk 
├─nvme0n1p1  259:1    0   976M  0 part /boot/efi
├─nvme0n1p2  259:2    0   1.8T  0 part /
└─nvme0n1p3  259:3    0  63.7G  0 part [SWAP]

S.M.A.R.T

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.

ed@local:~$ sudo smartctl --all /dev/nvme0 
smartctl 7.4 2023-08-01 r5530 [x86_64-linux-6.12.48+deb13-amd64] (local build)
Copyright (C) 2002-23, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF INFORMATION SECTION ===
Model Number:                       SAMSUNG MZVL22T0HDLB-00BLL
Serial Number:                      S75ZNE0W602153
Firmware Version:                   6L2QGXD7
PCI Vendor/Subsystem ID:            0x144d
IEEE OUI Identifier:                0x002538
Total NVM Capacity:                 2,048,408,248,320 [2.04 TB]
Unallocated NVM Capacity:           0
Controller ID:                      6
NVMe Version:                       1.3
Number of Namespaces:               1
Namespace 1 Size/Capacity:          2,048,408,248,320 [2.04 TB]
Namespace 1 Utilization:            248,372,908,032 [248 GB]
Namespace 1 Formatted LBA Size:     512
Namespace 1 IEEE EUI-64:            002538 b63101bf9d
Local Time is:                      Sat Oct 25 08:07:32 2025 CST
Firmware Updates (0x16):            3 Slots, no Reset required
Optional Admin Commands (0x0017):   Security Format Frmw_DL Self_Test
Optional NVM Commands (0x0057):     Comp Wr_Unc DS_Mngmt Sav/Sel_Feat Timestmp
Log Page Attributes (0x0e):         Cmd_Eff_Lg Ext_Get_Lg Telmtry_Lg
Maximum Data Transfer Size:         128 Pages
Warning  Comp. Temp. Threshold:     83 Celsius
Critical Comp. Temp. Threshold:     85 Celsius

Supported Power States
St Op     Max   Active     Idle   RL RT WL WT  Ent_Lat  Ex_Lat
 0 +     8.41W       -        -    0  0  0  0        0       0
 1 +     8.41W       -        -    1  1  1  1        0     200
 2 +     8.41W       -        -    2  2  2  2        0     200
 3 -   0.0500W       -        -    3  3  3  3     2000    1200
 4 -   0.0050W       -        -    4  4  4  4      500    9500

Supported LBA Sizes (NSID 0x1)
Id Fmt  Data  Metadt  Rel_Perf
 0 +     512       0         0

=== START OF SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED

SMART/Health Information (NVMe Log 0x02)
Critical Warning:                   0x00
Temperature:                        37 Celsius
Available Spare:                    100%
Available Spare Threshold:          10%
Percentage Used:                    0%
Data Units Read:                    43,047,167 [22.0 TB]
Data Units Written:                 25,888,438 [13.2 TB]
Host Read Commands:                 314,004,907
Host Write Commands:                229,795,952
Controller Busy Time:               2,168
Power Cycles:                       1,331
Power On Hours:                     663
Unsafe Shutdowns:                   116
Media and Data Integrity Errors:    0
Error Information Log Entries:      0
Warning  Comp. Temperature Time:    0
Critical Comp. Temperature Time:    0
Temperature Sensor 1:               37 Celsius
Temperature Sensor 2:               37 Celsius

Error Information (NVMe Log 0x01, 16 of 64 entries)
No Errors Logged

Self-test Log (NVMe Log 0x06)
Self-test status: No self-test in progress
No Self-tests Logged

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.

ed@local:~$ sudo fdisk -l
Disk /dev/nvme0n1: 1.86 TiB, 2048408248320 bytes, 4000797360 sectors
Disk model: SAMSUNG MZVL22T0HDLB-00BLL              
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 347D3F20-0228-436D-9864-22A5D36039D9

Device              Start        End    Sectors  Size Type
/dev/nvme0n1p1       2048    2000895    1998848  976M EFI System
/dev/nvme0n1p2    2000896 3867305983 3865305088  1.8T Linux filesystem
/dev/nvme0n1p3 3867305984 4000796671  133490688 63.7G Linux swap

Disk /dev/sda: 119.08 GiB, 127865454592 bytes, 249737216 sectors
Disk model: Storage Device  
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xa82a04bd

Device     Boot Start       End   Sectors   Size Id Type
/dev/sda1        2048 249737215 249735168 119.1G 83 Linux

Basisreparatur mit Konsistenzcheck: fsck

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.

Abonnement / Subscription

[English] This content is only available to subscribers.

[Deutsch] Diese Inhalte sind nur für Abonnenten verfügbar.

Network Attached Storage (NAS)

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.

Abonnement / Subscription

[English] This content is only available to subscribers.

[Deutsch] Diese Inhalte sind nur für Abonnenten verfügbar.

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:

Abonnement / Subscription

[English] This content is only available to subscribers.

[Deutsch] Diese Inhalte sind nur für Abonnenten verfügbar.

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.


Grazer Linux Tage 2019

Grazer Linux Tage 2019

Elmar Dott Apr. 27, 2019 1 min read

Conference: GLT 2019 – Challenges to create your own Open Source Project Weiterlesen →

Pfadfinder

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%

ed@local:~$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/snap/bin:/home/ed/Programs/maven/bin:/home/ed/.local/share/gem//bin:/home/ed/.local/bin:/usr/share/openjfx/lib

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.

export M2_HOME="/opt/maven"
export PATH=$PATH:$M2_HOME/bin

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.


Dokumente mit AnythingLLM und Ollama verarbeiten

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.


A Fool with a tool is still a fool

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

Referenzen

Abonnement / Subscription

[English] This content is only available to subscribers.

[Deutsch] Diese Inhalte sind nur für Abonnenten verfügbar.