Der grüne Punkt – Mythos Wiederverwendung

Als mir im Studium die Vorzüge der objektorientierten Programmierung mit Java schmackhaft gemacht wurden, war ein sehr beliebtes Argument die Wiederverwendung. Dass der Grundsatz „write once use everywhere“ in der Praxis dann doch nicht so leicht umzusetzen ist, wie es die Theorie suggeriert, haben die meisten Entwickler bereits am eigenen Leib erfahren. Woran liegt es also, dass die Idee der Wiederverwendung in realen Projekten so schwer umzusetzen ist? Machen wir also einen gemeinsamen Streifzug durch die Welt der Informatik und betrachten verschiedene Vorhaben aus sicherer Distanz.

(c) 2022 Elmar Dott, Java akuell Ausgabe 2, S.55 – 57

Wenn ich daran denke, wie viel Zeit ich während meines Studiums investiert habe, um eine Präsentationsvorlage für Referate zu erstellen. Voller Motivation habe ich alle erdenklichen Ansichten in weiser Voraussicht erstellt. Selbst rückblickend war das damalige Layout für einen Nichtgrafiker ganz gut gelungen. Trotzdem kam die tolle Vorlage nur wenige Male zum Einsatz und wenn ich im Nachhinein einmal Resümee ziehe, komme ich zu dem Schluss, dass die investierte Arbeitszeit in Bezug auf die tatsächliche Verwendung in keinem Verhältnis gestanden hat. Von den vielen verschiedenen Ansichten habe ich zum Schluss exakt zwei verwendet, das Deckblatt und eine allgemeine Inhaltsseite, mit der alle restlichen Darstellungen umgesetzt wurden. Die restlichen 15 waren halt da, falls man das künftig noch brauchen würde. Nach dieser Erfahrung plane ich keine eventuell zukünftig eintreffenden Anforderungen mehr im Voraus. Denn den wichtigsten Grundsatz in Sachen Wiederverwendung habe ich mit dieser Lektion für mich gelernt: Nichts ist so beständig wie die Änderung.

Diese kleine Anekdote trifft das Thema bereits im Kern. Denn viele Zeilen Code werden genau aus der gleichen Motivation heraus geschrieben. Der Kunde hat es noch nicht beauftragt, doch die Funktion wird er ganz sicher noch brauchen. Wenn wir in diesem Zusammenhang einmal den wirtschaftlichen Kontext ausblenden, gibt es immer noch ausreichend handfeste Gründe, durch die Fachabteilung noch nicht spezifizierte Funktionalität nicht eigenmächtig im Voraus zu implementieren. Für mich ist nicht verwendeter, auf Halde produzierter Code – sogenannter toter Code – in erster Linie ein Sicherheitsrisiko. Zusätzlich verursachen diese Fragmente auch Wartungskosten, da bei Änderungen auch diese Bereiche möglicherweise mit angepasst werden müssen. Schließlich muss die gesamte Codebasis kompilierfähig bleiben. Zu guter Letzt kommt noch hinzu, dass die Kollegen oft nicht wissen, dass bereits eine ähnliche Funktion entwickelt wurde, und diese somit ebenfalls nicht verwenden. Die Arbeit wird also auch noch doppelt ausgeführt. Nicht zu vergessen ist auch das von mir in großen und langjährig entwickelten Applikationen oft beobachtete Phänomen, dass ungenutzte Fragmente aus Angst, etwas Wichtiges zu löschen, über Jahre hinweg mitgeschleppt werden. Damit kommen wir auch schon zum zweiten Axiom der Wiederverwendung: Erstens kommt es anders und zweitens als man denkt.

Über die vielen Jahre, genauer gesagt Jahrzehnte, in denen ich nun verschiedenste IT- beziehungsweise Softwareprojekte begleitet habe, habe ich ein Füllhorn an Geschichten aus der Kategorie „Das hätte ich mir sparen können!“ angesammelt. Virtualisierung ist nicht erst seit Docker [1] auf der Bildfläche erschienen – es ist schon weitaus länger ein beliebtes Thema. Die Menge der von mir erstellten virtuellen Maschinen (VMs) kann ich kaum noch benennen – zumindest waren es sehr viele. Für alle erdenklichen Einsatzszenarien hatte ich etwas zusammengebaut. Auch bei diesen tollen Lösungen erging es mir letztlich nicht viel anders als bei meiner Office-Vorlage. Grundsätzlich gab es zwei Faktoren, die sich negativ ausgewirkt haben. Je mehr VMs erstellt wurden, desto mehr mussten dann auch gewertet werden. Ein Worst-Case-Szenario heutzutage wäre eine VM, die auf Windows 10 basiert, die dann jeweils als eine .NET- und eine Java-Entwicklungsumgebung oder Ähnliches spezialisiert wurde. Allein die Stunden, die man für Updates zubringt, wenn man die Systeme immer mal wieder hochfährt, summieren sich auf beachtliche Größen. Ein Grund für mich zudem, soweit es geht, einen großen Bogen um Windows 10 zu machen. Aus dieser Perspektive können selbsterstellte DockerContainer schnell vom Segen zum Fluch werden.

Dennoch darf man diese Dinge nicht gleich überbewerten, denn diese Aktivitäten können auch als Übung verbucht werden. Wichtig ist, dass solche „Spielereien“ nicht ausarten und man neben den technischen Erfahrungen auch den Blick für tatsächliche Bedürfnisse auf lange Sicht schärft.

Gerade bei Docker bin ich aus persönlicher Erfahrung dazu übergegangen, mir die für mich notwendigen Anpassungen zu notieren und zu archivieren. Komplizierte Skripte mit Docker-Compose spare ich mir in der Regel. Der Grund ist recht einfach: Die einzelnen Komponenten müssen zu oft aktualisiert werden und der Einsatz für jedes Skript findet in meinem Fall genau einmal statt. Bis man nun ein lauffähiges Skript zusammengestellt hat, benötigt man, je nach Erfahrung, mehrere oder weniger Anläufe. Also modifiziere ich das RUN-Kommando für einen Container, bis dieser das tut, was ich von ihm erwarte. Das vollständige Kommando hinterlege ich in einer Textdatei, um es bei Bedarf wiederverwenden zu können. Dieses Vorgehen nutze ich für jeden Dienst, den ich mit Docker virtualisiere. Dadurch habe ich die Möglichkeit, verschiedenste Konstellationen mit minimalen Änderungen nach dem „Klemmbaustein“-Prinzip zu rchestrieren. Wenn sich abzeichnet, dass ein Container sehr oft unter gleichen Bedienungen instanziiert wird, ist es sehr hilfreich, diese Konfiguration zu automatisieren. Nicht ohne Grund gilt für Docker-Container die Regel, möglichst nur einen Dienst pro Container zu virtualisieren.

Aus diesen beiden kleinen Geschichten lässt sich bereits einiges für Implementierungsarbeiten am Code ableiten. Ein klassischer Stolperstein, der mir bei der täglichen Projektarbeit regelmäßig unterkommt, ist, dass man mit der entwickelten Applikation eine eierlegende Wollmilchsau – oder, wie es in Österreich heißt: ein Wunderwutzi – kreieren möchte. Die Teams nehmen sich oft zu viel vor und das Projektmanagement versucht, den Product Owner auch nicht zu bekehren, lieber auf Qualität statt auf Quantität zu setzen. Was ich mit dieser Aussage deutlich machen möchte, lässt sich an einem kleinen Beispiel verständlich machen.

Gehen wir einmal davon aus, dass für eigene Projekte eine kleine Basisbibliothek benötigt wird, in der immer wiederkehrende Problemstellungen zusammengefasst werden – konkret: das Verarbeiten von JSON-Objekten [2]. Nun könnte man versuchen, alle erdenklichen Variationen im Umgang mit JSON abzudecken. Abgesehen davon, dass viel Code produziert wird, erzielt ein solches Vorgehen wenig Nutzen. Denn für so etwas gibt es bereits fertige Lösungen – etwa die freie Bibliothek Jackson [3]. Anstelle sämtlicher denkbarer JSON-Manipulationen ist in Projekten vornehmlich das Serialisieren und das Deserialisieren gefragt. Also eine Möglichkeit, wie man aus einem Java-Objekt einen JSON-String erzeugt, und umgekehrt. Diese beiden Methoden lassen sich leicht über eine Wrapper-Klasse zentralisieren. Erfüllt nun künftig die verwendete JSON-Bibliothek die benötigten Anforderungen nicht mehr, kann sie leichter durch eine besser geeignete Bibliothek ersetzt werden. Ganz nebenbei erhöhen wir mit diesem Vorgehen auch die Kompatibilität [4] unserer Bibliothek für künftige Erweiterungen. Wenn JSON im Projekt eine neu eingeführte Technologie ist, kann durch die Minimal-Implementierung stückweise Wissen aufgebaut werden. Je stärker der JSONWrapper nun in eigenen Projekten zum Einsatz kommt, desto wahrscheinlicher ist es, dass neue Anforderungen hinzukommen, die dann erst umgesetzt werden, wenn sie durch ein Projekt angefragt werden. Denn wer kann schon abschätzen, wie der tatsächliche Bedarf einer Funktionalität ist, wenn so gut wie keine Erfahrungen zu der eingesetzten Technologie vorhanden sind?

Das soeben beschriebene Szenario läuft auf einen einfachen Merksatz hinaus: Eine neue Implementierung möglichst so allgemein wie möglich halten, um sie nach Bedarf immer weiter zu spezialisieren.

Bei komplexen Fachanwendungen hilft uns das Domain-driven Design (DDD) Paradigma, Abgrenzungen zu Domänen ausfindig zu machen. Auch hierfür lässt sich ein leicht verständliches, allgemein gefasstes Beispiel finden. Betrachten wir dazu einmal die Domäne einer Access Control List (ACL). In der ACL wird ein Nutzerkonto benötigt, mit dem Berechtigungen zu verschiedenen Ressourcen verknüpft werden. Nun könnte man auf die Idee kommen, im Account in der ACL sämtliche Benutzerinformationen wie Homepage, Postadresse und Ähnliches abzulegen. Genau dieser Fall würde die Domäne der ACL verletzen, denn das Benutzerkonto benötigt lediglich Informationen, die zur Authentifizierung benötigt werden, um eine entsprechende Autorisierung zu ermöglichen.

Jede Anwendung hat für das Erfassen der benötigten Nutzerinformationen andere Anforderungen, weshalb diese Dinge nicht in eine ACL gehören sollten. Das würde die ACL zu sehr spezialisieren und stetige Änderungen verursachen. Daraus resultiert dann auch, dass die ACL nicht mehr universell einsatzfähig ist.

Man könnte nun auf die Idee kommen, eine sehr generische Lösung für den Speicher zusätzlicher Nutzerinformationen zu entwerfen
und ihn in der ACL zu verwenden. Von diesem Ansatz möchte ich abraten. Ein wichtiger Grund ist, dass diese Lösung die Komplexität der ACL unnötig erhöht. Ich gehe obendrein so weit und möchte behaupten, dass unter ungünstigen Umständen sogar Code-Dubletten entstehen. Die Begründung dafür ist wie folgt: Ich sehe eine generische Lösung zum Speichern von Zusatzinformationen im klassischen Content Management (CMS) verortet. Die Verknüpfung zwischen ACL und CMS erfolgt über die Benutzer-ID aus der ACL. Somit haben wir gleichzeitig auch zwischen den einzelnen Domänen eine lose Kopplung etabliert, die uns bei der Umsetzung einer modularisierten Architektur sehr behilflich sein wird.

Zum Thema Modularisierung möchte ich auch kurz einwerfen, dass Monolithen [5] durchaus auch aus mehreren Modulen bestehen können und sogar sollten. Es ist nicht zwangsläufig eine Microservice-Architektur notwendig. Module können aus unterschiedlichen Blickwinkeln betrachtet werden. Einerseits erlauben sie es einem Team, in einem fest abgegrenzten Bereich ungestört zu arbeiten, zum anderen kann ein Modul mit einer klar abgegrenzten Domäne ohne viele Adaptionen tatsächlich in späteren Projekten wiederverwendet werden.

Nun ergibt sich klarerweise die Fragestellung, was mit dem Übergang von der Generalisierung zur Spezialisierung gemeint ist. Auch hier hilft uns das Beispiel der ACL weiter. Ein erster Entwurf könnte die Anforderung haben, dass, um unerwünschte Berechtigungen falsch konfigurierter Rollen zu vermeiden, die Vererbung von Rechten bestehender Rollen nicht erwünscht ist. Daraus ergibt sich dann der Umstand, dass jedem Nutzer genau eine Rolle zugewiesen werden kann. Nun könnte es sein, dass durch neue Anforderungen der Fachabteilung eine Mandantenfähigkeit eingeführt werden soll. Entsprechend muss nun in der ACL eine Möglichkeit geschaffen werden, um bestehende Rollen und auch Nutzeraccounts einem Mandanten zuzuordnen. Eine Domänen-Erweiterung dieser hinzugekommenen Anforderung ist nun basierend auf der bereits bestehenden Domäne durch das Hinzufügen neuer Tabellenspalten leicht umzusetzen.

Die bisher aufgeführten Beispiele beziehen sich ausschließlich auf die Implementierung der Fachlogik. Viel komplizierter verhält sich das Thema Wiederverwendung beim Punkt der grafischen Benutzerschnittelle (GUI). Das Problem, das sich hier ergibt, ist die Kurzlebigkeit vieler chnologien. Java Swing existiert zwar noch, aber vermutlich würde sich niemand, der heute eine neue Anwendung entwickelt, noch für Java Swing entscheiden. Der Grund liegt in veraltetem Look-and-Feel der Grafikkomponenten. Um eine Applikation auch verkaufen zu können, darf man den Aspekt der Optik nicht außen vor lassen. Denn auch das Auge isst bekanntlich mit. Gerade bei sogenannten Green-Field-Projekten ist der Wunsch, eine moderne, ansprechende Oberfläche anbieten zu können, implizit. Deswegen vertrete ich die Ansicht, dass das Thema Wiederverwendung für GUI – mit wenigen Ausnahmen – keine wirkliche Rolle spielt.

Lessons Learned

Sehr oft habe ich in der Vergangenheit erlebt, wie enthusiastisch bei Kick-off-Meetings die Möglichkeit der Wiederverwendung von Komponenten in Aussicht gestellt wurde. Dass dies bei den verantwortlichen Managern zu einem Glitzern in den Augen geführt hat, ist auch nicht verwunderlich. Als es dann allerdings zu ersten konkreten Anfragen gekommen ist, eine Komponente in einem anderen Projekt einzusetzen, mussten sich alle Beteiligten eingestehen, dass dieses Vorhaben gescheitert war. In den nachfolgenden Retrospektiven sind die Punkte, die ich in diesem Artikel vorgestellt habe, regelmäßig als Ursachen identifiziert worden. Im Übrigen genügt oft schon ein Blick in das Datenbankmodell oder auf die Architektur einer Anwendung, um eine Aussage treffen zu können, wie realistisch eine Wiederverwendung tatsächlich ist. Bei steigendem Komplexitätsgrad sinkt die Wahrscheinlichkeit, auch nur kleinste Segmente erfolgreich für eine Wiederverwendung herauslösen zu können.

Referenzen
[1] https://www.docker.com
[2] https://www.json.org
[3] https://github.com/FasterXML/jackson/
[4] https://entwickler.de/api/futurama-nichts-ist-so-bestandig-wiedie-veranderung/
[5] https://entwickler.de/microservices/slice-down-the-monolith-001/

Meeting Culture for Experts

After I started my career in the software industry I needed to participate in a lot of different meetings. Since the most companies transformed to agile the amount of meetings increased. Many developers have equal perceptions about meetings like me. The most of those meetings are just time wasting.

Often the person who had send the meeting invitations was not thinking about the different between quality and quantity. This thoughts are not new. Long ago Tom DeMarco described this situations in his books. His solution works until today and you find it also in explanations about how agile communication should organized. Just put the persons together you really need to make decisions. Less is always better than to many.

Another thing about meetings I figured out by my own experience, is when technicians and non technicians try to communicate. If you just watch this as an external observer it could be a funny entertainment, like the parody in the video I placed below the article. But if you involved as an expert to help a CTO taking decisions and they do not understand what you talking about, it drives you into frustrations.

Yegor Bugayenko mentioned in his podcast Shift-M that a CTO is far away from hands on code. I had recognized the same. And often this persons also far away from a deep technical understanding. The same I can say about project managers. In my perception, I often got the idea this managers won’t to understand technical details as well, to take good decisions. Well sometimes technicians exaggerate also with the level of information they give. Not everybody need to get the full details of a topic. A realistic overall picture, maybe a bit more details than a simple synopsis could make the things for everybody more easy.

A very old story to illustrate this topic was in the early 2000, when the questions pop up to implement a fat or a thin client. For this decision-guys thin client was sounding more smart, also they took this option, without understanding the consequences. After a while the project was running, they start to blame around that the costs are exploding and the result was not what they expect. In a retrospective is very easy to understand why the problems occurred. The manager had not specified well the browser support for the thin client. To secure all the compatibility was extremely cost intense. Also to keep the UI up to date will produce in the future costs, because the browsers will not stay from today the same like 10 years in the future. The same discussions we always have in every time period. Not so long ago was the question monolith or microservice? Simon Brown answered this question very straight to the point: „If you can’t build a monolith, what makes your think microservices are the answer?“ And what are the drama topics in 2020? Of course cloud services, Kubernetes and serverless.

For me it would be great when the persons taking decisions, minimum want to understand technical things and their consequences. If we focus more on the soft skills mangers should have, less software projects would fail. In between we keep going to give developers rhetoric trainings, to give them the capability to talk unspecific like a salesman.

7 Totsünden für Software Projekte

Das Scheitern von Projekten ist Gegenstand vieler Publikationen. Seit Jahrzehnten versucht man diesem Umstand durch verschiedenste Methodiken und Werkzeuge mehr oder minder erfolgreich beizukommen. Obwohl auf den ersten Blick die Gründe eines Misserfolges mannigfaltig scheinen, kann überwiegend schlechtes Management als Problemquelle identifiziert werden. So verweist auch der nachfolgend übersetzte Artikel von Yegor Bugayenko, welche Umstände dafür sorgen tragen können, das Projekte in schlechtes Fahrwasser geraten.

Wartbarkeit gehört zu den wertvollsten Tugenden moderner Software Entwicklung. Eine einfache Möglichkeit Wartbarkeit zu messen, besteht darin die Arbeitszeit zu messen, welche ein Entwickler benötigt um in einem neuen Projekt eigenständig ernsthafte Änderungen vorzunehmen. Je mehr Zeit benötigt wird um so schlechter ist die Wartbarkeit. In einigen Projekten ist diese Zeitanforderung beinahe unendlich. Was einfach ausgedrückt bedeutet, das diese Projekte schlichtweg nicht wartbar sind. Ich glaube das es sieben fundamentale und fatale Anzeichen gibt, das Projekte unwartbar werden. Hier sind sie:

1. Anti-Pattern

Unglücklicherweise sind die Programmiersprachen, welche wir benutzen zu flexibel. Sie ermöglichen zu viel und unterbinden zu wenig. Java zum Beispiel, besitzt keine Restriktionen ein ganze Anwendung mit ein paar tausend Methoden in nur eine Klasse zu packen. Technisch gesehen wird die Anwendung kompilieren und laufen, dennoch handelt es sich um das bekannte Anti-Pattern God Object.

Somit sind Anti-Pattern technisch akzeptierte Möglichkeiten eines Entwurfes, welcher allgemein als schlecht anerkannt ist. Es gibt für ede Sprache unzählige Anti-Pattern. Ihre Gegenwartin unserem Produkt is gleichzusetzen mit einem Tumor in einem lebendem Organismus. Wenn er einmal beginnt zu wachsen ist es sehr schwierig ihm Einhalt zu gebieten. Möglicherweise stirbt der gesamte Organismus. Möglicherweise muss die gesamte Anwendung neu geschrieben werden, weil sie unwartbar geworden ist.

Wenn nur einige Anti-Pattern zugelassen werden, werden denen möglicherweise schnell weitere folgen und der “Tumor” beginnt zu wachsen.

Dies trifft besonders auf objektorientierte Sprachen (Java, C++, Ruby und Phyton) zu, vor allem wegen ihrer Erblast aus prozeduralen Sprachen (C, Fortran und COBOL) und weil Entwickler zu einer imperativen und prozeduralen Denkweise neigen. Unglücklicherweise.

Übrigens empfehle ich zu der Liste von Anti-Pattern [2] einige Dinge ebenfalls als schlechte Programmierlösungen [3].

Meine einzige praktische Empfehlung an dieser Stelle ist lesen und lernen. Vielleicht helfen dieses Bücher [4] oder mein eigenes [5]. Eine generelle skeptische Einstellung zur eigenen Arbeit und keine Entspannungshaltung wenn es nur funktioniert. Genauso wie bei Krebs. Je früher es diagnostiziert wird um so größer ist die Chance zu überleben.

2. Unverfolgte Änderungen

Bei einem Blick auf die commit history sollte man in der Lage sein für jede einzelne Änderung sagen zu können was geändert wurde, wer die Änderung vorgenommen hat und warum die Änderung statt gefunden hat. Es sollte nicht mehr als einige Sekunden benötigen um diese drei Fragen zu beantworten. In den meisten Projekten ist das nicht der Fall. Hier sind einige praktische Vorschläge:

  • Benutze stets Tickets: Ganz gleich wie klein das Projekt oder das Team ist, selbst wenn es nur eine Person umfasst. Erzeugt stets Tickets (Z. B. GitHub Issues) für jedes Problem welches gelöst wird. Erläutert das Problem kurz im Ticket und dokumentiert die Lösungsansätze. Das Ticket sollte als temporäres Sammelbecken für alle Informationen die sich auf das Problem beziehen dienen. Alles was in Zukunft dazu beitragen kann die paar „komischen“ commits zu verstehen sollte in dem Ticket veröffentlicht werden.
  • Referenzieren von Tickets in den Commits: Unnötig zu erwähnen ist das jeder Commit eine Beschreibung (Message) haben muss. Commits ohne Beschreibung gehören zu einer sehr unsauberen Arbeitsweise, die ich hier nicht mehr ausführen muss. Allerdings eine saloppe Beschreibung wird den Ansprüchen ebenfalls nicht gerecht. So sollte die Beschreibung stets mit der Ticketnummer beginnen, an der gerade gearbeitet wurde. GitHub beispielsweise verknüpft automatisch Commits mit den zugehörigen Tickets um die Nachverfolgbarkeit von Änderungen zu gewährleisten.
  • Nicht alles löschen: Git ermöglicht sogenannte „forched“ push, welche den gesamten remote Branch überschreiben.Dies ist nur ein Beispiel wie die Entwicklungshistorie zerstört werden kann. Oft habe ich beobachten können wie Leute ihre Kommentare in GitHub gelöscht haben, um die Tickets zu bereinigen. Das ist schlichtweg falsch. Lösche niemals alles. Behaltet eure Historie ganz gleich wie schlecht oder unaufgeräumt sie erscheinen mag.

3. Ad Hoc Releases

Jedes Stück Software muss vor einer Auslieferung zum Endkunden paketiert werden. Handelt es sich um eine Java Bibliothek ist das Paketformat eine .jar Datei die in die üblichen Repositorien abgelegt wurde. Ist es eine Webapplikation muss sie auf eine Plattform installiert werden. Gleich wie groß oder klein das Produkt ist es existiert eine Standartprozedur für testen, paketieren und ausliefern.

Eine optimale Lösung könnte eine Automatisierung dieser Vorgänge sein. Dies ermöglicht eine Ausführung über die Kommandozeile mit einer einfachen Anweisung.

$ ./release.sh ... DONE (took 98.7s)

Die meisten Projekte sind sehr weit entfernt von solch einem Ansatz. Ihr Releaseansatz beinhaltet einige Magie. Die Leute welche dafür verantwortlich sind, auch bekannt als DevOps, müssen lediglich einige Knöpfe drücken, irgendwo einloggen und Metriken prüfen et Cetera. Solch ein Ad Hoc Releaseprozess ist ein sehr typisches Zeichen für die gesamte Software Entwicklungsindustrie.

Ich habe einige praktische Ratschläge zu geben: automatisiert. Ich verwende rultor.com dafür, aber es steht natürlich frei jedes beliebe andere Werkzeug dafür einzusetzen. Das einzig wichtige ist das der gesamte Prozess vollständig automatisiert ist und von der Kommandozeile ausgeführt werden kann.

4. Freiwillige statische Analyse

Statische Analyse [6] ist das, was den Quelltext besser aussehen lässt. Implizit sind wir bei dem Vorgang dazu eingeladen den Code auch effektiver zu machen. Dies gelingt allerdings nur wenn das gesamte Team dazu angehalten ist den Vorgaben der statischen Analysewerkzeuge zu folgen. Ich schrieb bereits darüber in [7]. Für Java Projekte hab ich qulice.com und für Ruby Projekte rubocop verwendet. Es gibt sehr viele ähnliche Werkzeuge für nahezu jede Programmiersprache.

Jedes Tool kann verwendet werden, solange es für alle Verpflichtend ist. In vielen Projekten in denen statische Analyse in Verwendung kommt, erzeugen die Entwickler lediglich aufgehübschte Reports und behalten ihre alten Programmier-Gewohnheiten bei. Solche freiwilligen Ansätze bringen keine Verbesserungen für das Projekt. Sie erzeugen lediglich eine Illusion von Qualität.

Mein Rat ist, dass die statische Analyse ein verpflichtender Schritt der Deployment Pipline ist. Ein Build kann nur dann erfolgreich sein, wenn keine der statischen Regeln verletzt wurden.

5. Unbekannte Testabdeckung

Einfach ausgerückt bedeutet Testabdeckung in welchen Grad die Software durch Unit- oder Integrationstests getestet wurde. Je höher die Testabdeckung ist, us so mehr Code wurde durch die Testfälle ausgeführt. Offensichtlich ist eine hohe Abdeckung eine gute Sache.

Wie immer kennen viele Entwickler den Grad ihre Testabdeckung nicht. Sie messen diese Metrik einfach nicht. Vielleicht haben sie einige Testfälle aber niemand vermag zu sagen wie tief diese die Software überprüfen und welche Teile nicht getestet wurden. Diese Situation ist weitaus schlimmer als eine niedrige Testabdeckung welche jedem bekannt ist.

Eine hohe Testabdeckung ist keine Garantie für gute Qualität, das ist offensichtlich. Aber eine unbekannte Testabdeckung ist ein eindeutiger Indikator von Wartbarkeitsproblemen. Wenn eine neuer Entwickler in das Projekt integriert wird, sollte er in der Lage sein einige Änderungen vorzunehmen und sehen wie die Testabdeckung sich dadurch verändert. Idealerweise sollte wie Testabdeckung auf gleiche Weise wie statische Analyse überprüft werden. Der Buld sollte fehlschlagen wenn die Voreinstellung unterschritten wird. Idealerweise beträgt die Testabdeckung um die 80%.

6. Nonstop Entwicklung

Was ich mit nonstop meine ist Entwicklung ohne Meilensteine und Releases. Egal welche Art von Software implementiert wird, sie muss Released und die Ergebnisse regelmäßig visualisiert werden. Ein Projekt ohne eine eindeutige Releasehistorie ist ein unwartbares Chaos.

Der Grund dafür ist, das Wartbarkeit nur dann möglich ist, wenn der Quelltext gelesen und auch verstanden wurde.

Wenn ich einen Blick auf die Sourcen werfe, den zugehörigen Commits und der Release Historie sollte ich in der Lage sein zu sagen was die Intension des Autors war. Was passierte im Projekt vor einem Jahr? Wie steht es mit dem aktuellen Status? Wie sind die künftigen Schritte geplant? Alle diese Informationen müssen Bestandteil des Quelltextes sein und noch viel wichtiger, in der Git Historie.

Git Tags und GitHub Release Notes sind zwei wirkungsvolle Instrumente die mir diese Informationen zu Verfügung stellen. Nutze sie in vollem Umfang. Ebenso sollte nicht vergessen werden, das jede binäre Version des Produktes als ständiger Download verfügbar sein muss. Das bedeutet das ich in der Lage sein sollt die Version 0.1.3 herunter zu aden und zu testen, selbst wenn das Projekt bereits an der Version 3.4 arbeitet.

7. Undokumentierte Interfaces

Jede Software hat Schnittstellen, die verwendet werden sollten. Handelt es sich um eine Ruby gem, so existieren Klassen und Methoden die von Endanwendern Verwendung finden. Geht es um eine Webapplikation so gibt es Webseiten welche von einem Endbenutzer aufgerufen werden um mit der Anwendung zu interagieren. Jedes Software Projekt hat also ein Interface welches ausführlich beschreiben werden muss.

Wie mit den andern Punkten, welche bereits erwähnt wurden handelt es sich hierbei auch um Wartbarkeit. Als neuer Programmierer in einem Projekt beginnt die Einarbeitung bei den Interfaces. Jeder sollte daher verstehen was die Aufgabe des Interfaces ist und wie es benutzt werden kann.

Ich spreche von der Dokumentation für die Benutzer, nicht für Entwickler. Im allgemeinen bin ich gegen Dokumentation innerhalb der Software. An dieser Stelle stimme ich vollständig mit dem Agilen Manifest [7] überein. Funktionierende Anwendungen sind wichtiger als ausschweifende Dokumentation. Aber das meint nicht das Referenzieren auf eine externe Dokumentation welche für die Anwender gedacht ist.

Endanwender Interaktion mit der Anwendung muss sauber dokumentiert werden.

Handelt es sich um eine Bibliothek, so sind die Anwender Entwickler welche das Produkt verwenden und es nicht durch eigenen Code erweitern. Die Nutzung erfolgt ausschließlich als Black Box.

Diese Kriterien verwenden wir um Open Source Projekte für unseren Award [8] zu evaluieren.

Resourcen

[1] Original Artikel: https://www.yegor256.com/2015/06/08/deadly-sins-software-project.html
[2] https://en.wikipedia.org/wiki/Anti-pattern
[3] https://www.yegor256.com/2014/09/10/anti-patterns-in-oop.html
[4] https://www.yegor256.com/2015/04/22/favorite-software-books.html
[5] https://www.yegor256.com/elegant-objects.html
[6] https://en.wikipedia.org/wiki/Static_program_analysis
[7] http://agilemanifesto.org
[8] https://www.yegor256.com/2015/04/16/award.html

The new Java Release Cycle

After Oracle introduces the new release cycle for Java I was not convinced of this new strategy. Even today I still have a different opinion. One of the point I criticize is the disregard of semantic versioning. Also the argument with this new cycle is more easy to deliver more faster new features, I’m not agree. In my opinion could occur some problems in the future. But wait, let’s start from the beginning, before I share my complete thoughts at once.

The six month release cycle Oracle announced in 2017 for Java ensure some insecurity to the community. The biggest fear was formulated by the popular question: Will be Java in future not anymore for free? Of course the answer is a clear no, but there are some impacts for companies they should be aware of it. If we think on huge Applications in production, are some points addressed to the risk management and the business continuing strategy. If the LTS support for security updates after the 3rd year of a published release have to be paid, force well defined strategies for updates into production. I see myself spending in future more time to migrate my projects to new java versions than implement new functionalities. One solution to avoid a permanent update orgy is move away from the Oracle JVM to OpenJDK.

In professional environment is quite popular that companies define a fixed setup to keep security. When I always are forced to update my components without a proof the new features are secure, it could create problems. Commercial projects running under other circumstances and need often special attention. Because you need a well defined environment where you know everything runs stable. Follow the law never touch a running system.

Absolutely I can understand the intention of Oracle to take this step. I guess it’s a way to get rid of old buggy and insecure installations. To secure the internet a bit more. Of course you can not support decades old deprecated versions. This have a heavy financial impact. but I wish they had chosen an less rough strategy. It’s sadly that the business often operate in this way. I wished it exist a more trustful communication.

By experience of preview releases of Java it always was taken a time until they get stable. In this context I remind myself to some heavy issues I was having with the change to 64 bit versions. The typical motto: latest is greatest, could be dangerous. Specially time based releases are good candidates for problems, even when the team is experienced. The pressure is extremely high to deliver in time.

Another fact which could discuss is the semantic versioning. It is a very powerful process, I always recommend. I ask myself If there really every six months new language features to have the reason increasing the Major number? Even for patches and enhancements? But what happens when in future is no new language enhancement? By the way adding by force often new features could decrease quality. In my opinion Java includes many educative features and not every new feature request increase the language capabilities. A simple example is the well known GOTO statement in other languages. When you learn programming often your mentor told you – it exist something if you see it you should run away. Never use GOTO. In Java inner classes I often compare with GOTO, because I think this should avoid. Until now I didn’t find any case where inner classes not a hint for design problems. The same is the heavy usage of functional statements. I can’t find any benefit to define a for loop as lambda function instead of the classical way.

In my opinion it looks like Oracle try to get some pieces from the cake to increase their business. Well this is not something bad,. But in the view of project management I don’t believe it is a well chosen strategy.

Read more: https://www.infoq.com/news/2017/09/Java6Month/

14
Which is your Java Version you still use?

The not mentioned versions in this list never had any relevant meaning.

Sie bekommen, was sie verdienen

IT-Professionals bekommen schon zu Beginn ihrer Karriere kuriose Anfragen. So auch ich. Bereits während meines Studiums klingelte hin und wieder das Telefon und besonders kluge Menschen erklärten mir, wie ich für sie so etwas wie Facebook nachprogrammieren könne. Natürlich ohne Bezahlung.

(c) 2019 Marco Schulz, Java aktuell Ausgabe 2, S.64-65

Die pfiffige Idee dieser Zeitgenossen war es, das ich für sie kostenlos eine Plattform erstelle, natürlich exklusiv nach ihren Wünschen. Dank deren hervorragender Vernetzung würde das Ganze sehr schnell erfolgreich und wir könnten den Gewinn untereinander aufteilen. Ich wollte dann immer wissen, wozu ich für die Entwicklung eines Systems, dessen Kosten und Risiken ich allein zu tragen habe, einen Partner benötige, um dann mit ihm den Gewinn zu teilen. Diese Frage beendete solche Gespräche recht schnell.

Vor nicht allzu langer Zeit erreichte mich wieder einmal eine Projektanfrage mit einem umfangreichen Skill-Set zu einem offerierten Stundenlohn, der bereits für Studenten unverschämt gering ausfiele. Dies erinnerte mich an einen sehr sarkastischen Artikel von Yegor Bugayenko aus dem Jahre 2016, den ich hier ins Deutsche übertragen habe:

Um Software erstellen zu können, benötigt man Programmierer. Unglücklicherweise. Sie sind in aller Regel teuer, faul und meistens unkontrollierbar. Die Software, die sie erstellen, funktioniert vielleicht oder vielleicht auch nicht. Trotzdem erhalten sie jeden Monat ihren Lohn. Aus diesem Grund ist es immer eine gute Idee, möglichst wenig zu zahlen. Wie dem auch sei. Manchmal erklären sie einem, wie unterbezahlt sie sind, und kündigen einfach. Aber wie will man dies unterbinden? Leider ist es uns nicht mehr gestattet, gewalttätig zu sein, aber es gibt einige andere Möglichkeiten. Last mich dies genauer erläutern.

Gehälter geheim halten

Es ist offensichtlich: Sie dürfen sich nicht über ihre Gehälter austauschen. Diese Information ist geheim zu halten. Ermahnt sie oder noch besser schreibt einen Geheimhaltungs-Paragraph in ihren Vertrag, der verhindert, dass über Löhne, Boni, Vergütungspläne gesprochen wird. Sie müssen fühlen, dass diese Information giftig ist. So dass sie sich nie über dieses Thema unterhalten. Wenn das Einkommen ihrer Kollegen unbekannt ist, kommen weniger Fragen nach Gehaltserhöhungen auf.

Zufällige Lohnerhöhungen

Es sollte kein erkennbares System geben, wie Lohnerhöhungen oder Kündigungen entschieden werden. Lohnerhöhungen werden ausschließlich nach Bauchgefühl verteilt, nicht etwa, weil jemand produktiver oder effektiver wurde. Entscheidungen sollten unvorhersehbar sein. Unvorhersagbarkeit erzeugt Angst und dies ist genau das, was wir wollen. Sie sind eingeschüchtert ihrem Auftraggeber gegenüber und werden sich lange Zeit nicht beschweren, wie unterbezahlt sie sind.

Keine Konferenzen

Es sollte ihnen nicht gestattet sein, an Meetups oder Konferenzen teilzunehmen. Dort könnten sie möglicherweise auf Vermittler treffen und herausfinden, dass ihre Bezahlung nicht fair genug ist. Es sollte die Idee verbreitet werden, dass Konferenzen lediglich Zeitverschwendungen sind. Es ist besser, Veranstaltungen im Büro durchzuführen. Sie haben immer zusammenzubleiben und niemals auf Programmierer aus anderen Unternehmen zu treffen. Je weniger sie wissen, desto sicherer ist man.

Keine Heimarbeit

Das Büro muss zu einem zweiten Zuhause werden. Besser noch, zum wichtigsten Platz in ihrem Leben. Sie müssen jeden Tag anwesend sein, am Schreibtisch, mit einem Computer, einem Stuhl und einer Ablage. Sie sind emotional verbunden mit ihrem Arbeitsplatz. So wird es viel schwieriger, ihn eines Tages zu kündigen, ganz gleich wie unterbezahlt sie auch sind. Sie sollten niemals eine Erlaubnis bekommen, per Remote zu arbeiten. Sie könnten dann beginnen, von einem neuen Zuhause und einem stattlicheren Gehalt zu träumen.

Überwacht sie

Es ist dafür zu sorgen, dass sie firmeneigene Systeme wie E-Mail, Computer, Server und auch Telefone nutzen. Darauf ist dann gängige Überwachungssoftware installiert, die sämtliche Nachrichten und Aktivitäten protokolliert. Idealerweise existiert eine Sicherheitsabteilung, um die Programme zu überwachen und bei abnormalem oder unerwartetem Verhalten das Management zu informieren. Videokameras sind auch sehr hilfreich. Jeglicher Kontakt zu anderen Unternehmen ist verdächtig. Angestellte sollten wissen, dass sie überwacht werden. Zusätzliche Angst ist immer hilfreich.

Vereinbarungen mit Mitbewerbern

Kontaktiert die größten Mitbewerber der Region und stellt sicher, dass keine Entwickler abgeworben werden, solange sie dies ebenfalls nicht tun. Falls sie diese Absprache zurückweisen, ist es gut, einige ihrer Schlüsselpersonen abzuwerben. Einfach durch das In–Aussicht-Stellen des doppelten bisherigen Gehalts. Natürlich will man sie nicht wirklich engagieren. Aber diese Aktion rüttelt den lokalen Markt ordentlich durch und Mitbewerber fürchten einen. Sie sind schnell einverstanden, keine deiner Entwickler jemals zu berühren.

Etabliert gemeinsame Werte

Unterzieht sie einer regelmäßigen Gehirnwäsche in gemeinsamen Jubelveranstaltungen, in denen begeistert verkündet wird, wie toll die Firma ist, was für großartige Ziele alle haben und wie wichtig die Zusammenarbeit als Team ist. Die Zahlen auf der Gehaltsabrechnung erscheinen weniger wichtig, im Vergleich zu einem Multi-Millionen-Euro-Vorhaben, das den Markt dominieren soll. Sie werden sich dafür aufopfern und eine recht lange Zeit wird dieser Trick motivieren.

Gründe eine Familie

Gemeinsame Firmenveranstaltungen, freitags Freibier, Team-Buil-ding-Veranstaltungen, Bowling, Geburtstagsfeiern, gemeinsame Mittagessen und Abendveranstaltungen – das sind Möglichkeiten, um das Gefühl zu erzeugen, dass die gesamte Firma die einzige Familie ist. In einer Familie spricht man als gutes Mitglied auch nicht über Geld. Korrekt? Die Frage nach einer Gehaltsvorstellung gilt als Verrat an der Familie. Aus diesem Grund werden sie davon Abstand nehmen.

Stresst sie

Sie dürfen sich nicht entspannt fühlen, das ist nicht zu unserem Vorteil. Sorgt für kurze Abgabetermine, komplexe Problemlösungen und ausreichend Schuldgefühle. Niemand wird nach einer Gehaltserhöhung fragen, wenn er sich schuldig fühlt, die Projektziele wieder einmal nicht erreicht zu haben. Daher sind sie so oft wie möglich für ihre Fehler zur Verantwortung zu ziehen.

Versprechungen machen

Es ist nicht notwendig, die Versprechen einzuhalten, aber sie müssen gemacht werden. Versprecht ihnen, das Gehalt demnächst zu erhöhen oder künftige Investitionen oder die Ausfertigung eines unbefristeten Abseitsvertrags. Natürlich unter der Bedingung, dass die Zeit dafür auch reif ist. Es ist sehr wichtig, dass die Versprechungen an ein Ereignis geknüpft sind, das man selbst nicht beeinflussen kann, um die eigenen Hände stets in Unschuld zu waschen.

Kauft ihnen weiche Sessel und Tischtennisplatten

Ein paar winzige Ausgaben für diese lustigen Bürosachen werden schnell kompensiert durch den Hungerlohn, den die Entwickler ausbezahlt bekommen. Eine hübsche, professionelle Kaffeemaschine kostet 1.000 Euro und spart pro Programmierer jeden Monat zwischen 200 bis 300 Euro ein. Rechnet es aus. Erstellt eine eigene Regel, die besagt, bevor irgendjemand eine Gehaltserhöhung bekommt, ist es sinnvoller, eine neue PlayStation für das Büro zu kaufen. Erlaubt ihnen, ihre Haustiere mit ins Büro zu bringen, und sie bleiben länger für weniger Geld.

Gut klingende Titel

Bezeichnet sie als Vizepräsident, beispielsweise „VP für Entwicklung“, „technischer VP“, VP von was auch immer. Keine große Sache. Aber sehr wichtig für Angestellte. Die Bezahlung hat so weitaus weniger Stellenwert als der Titel, den sie in ihre Profile auf sozialen Netzwerken schreiben können. Wenn alle Vizepräsidenten besetzt sind, versuche einmal Senior Architekt oder Lead Technical etc.

Überlebenshilfe

Die meisten Programmierer sind etwas unbeholfen wenn es darum geht, ihr Geld zu verwalten. Sie wissen einfach nicht, wie man eine Versicherung abschließt, die Rente organisiert, oder einfach nur, wie man Steuern zahlt. Natürlich erhalten sie Hilfe, nicht unbedingt zu ihren Gunsten. Aber sie werden glücklich sein, sich in euren Händen sicher fühlen und niemals daran denken, das Unternehmen zu verlassen. Niemand wird nach einer Lohnerhöhung fragen, weil sie sich schlecht fühlen, solche Geschäfte in die eigene Hand zu nehmen. Seid ihnen Vater oder Mutter – sie werden ihre Rolle als Kind annehmen. Es ist ein bewährtes Modell. Es funktioniert.

Sei ein Freund

Das ist die letzte und wirkungsvollste Methode. Sei ein Freund der Programmierer. Es ist verflixt schwierig, mit Freunden über Geld zu verhandeln. Sie sind nicht in der Lage, das einfach in Angriff zu nehmen. Sie bleiben und arbeiten gern für weniger Geld, einfach weil wir Freunde sind. Wie man zum Freund wird? Gut. Trefft ihre Familien, lade sie zum Essen in dein Haus ein, kleine Aufmerksamkeiten zu Geburtstagen – all diese Sachen. Sie sparen eine Menge Geld. Habe ich noch etwas vergessen?

Quelle
• https://www.yegor256.com/2016/12/06/how-to-pay-programmers-less.html