Das BugFix Bingo

Wenn Sie einen Weg finden möchten, negative Stimmung zwischen Testern und Entwicklern in etwas Positives zu verwandeln, haben wir hier eine tolle Lösung. Die Idee, die ich vorstellen möchte, ist zwar schon recht alt, aber auch heute noch in unserer schönen neuen DevOps-Welt ein Dauerbrenner.

Vor vielen Jahren stieß ich im Internet auf eine PDF-Datei namens „Bug Fix Bingo“. Ein nettes, lustiges Spiel für IT-Profis. Ursprünglich wurde dieses kleine, witzige Spiel von der Softwaretestfirma K. J. Ross & Associates entwickelt. Leider ist die Originalseite längst verschwunden, daher habe ich beschlossen, diese tolle Idee in diesem Blogbeitrag festzuhalten.

Ich kann dieses Spiel auch Leuten empfehlen, die sich nicht so intensiv mit Tests beschäftigen, aber an vielen IT-Meetings teilnehmen müssen. Drucken Sie einfach die Datei aus, bringen Sie ein paar Kopien zum nächsten Meeting mit und freuen Sie sich auf das Geschehen. Ich habe es mehrmals gespielt. Neben dem Spaß, den wir hatten, hat es etwas verändert. Schauen wir uns also das Konzept und die Regeln an.

Bug Fix Bingo basiert auf einem traditionellen Bingo, nur mit ein paar Anpassungen. Jeder kann ohne große Vorbereitung mitmachen, denn es ist ganz einfach. Anstelle von Zahlen werden beim Bingo Aussagen von Entwicklern in Defect-Review-Meetings verwendet, um Felder zu markieren.

Regeln:

  1. Bingo-Felder werden markiert, wenn ein Entwickler während der Fehlerbehebungssitzungen die passende Aussage macht.
  2. Tester müssen sofort „Bingo“ rufen, sobald sie eine Reihe von fünf Feldern horizontal, vertikal oder diagonal vervollständigt haben.
  3. Aussagen, die aufgrund eines Fehlers entstehen, der später als „verzögert“, „wie vorgesehen“ oder „nicht zu beheben“ eingestuft wird, sollten als nicht markiert klassifiziert werden.
  4. Fehler, die nicht in einem Vorfallsbericht gemeldet werden, können nicht verwendet werden.
  5. Aussagen sollten zur späteren Bestätigung zusätzlich zum Fehler im Fehlerverfolgungssystem erfasst werden.
  6. Jeder Tester, der alle 25 Aussagen markiert, erhält umgehend zwei Wochen Stressurlaub.
  7. Jeder Entwickler, der alle 25 Aussagen verwendet, sollte für mindestens sechs Monate zur Umschulung in die Testgruppe abgeordnet werden.
Auf meinem Rechner funktioniert es.”“Wo waren Sie, als das Programm explodierte?”“Warum willst du das auf diese Art machen?”“Sie können diese Version nicht auf Ihrem System verwenden.”“Auch wenn es nicht funktioniert, wie fühlt es sich an?”
“Haben Sie Ihr System auf Viren überprüft?”“Jemand muss meinen Code geändert haben.”“Es funktioniert, wurde aber nicht getestet.”“DAS kann nicht die Quelle dieses Moduls in Wochen sein!”“Ich kann nichts testen!”
“Es ist nur ein unglücklicher Zufall.”“Sie müssen die falsche Version haben.”“Ich habe dieses Modul seit Wochen nicht mehr berührt.”“Irgendetwas stimmt nicht mit Ihren Daten.”“Was hast du falsch eingegeben, dass es abgestürzt ist?”
“Es muss ein Hardwareproblem sein.”“Wie ist das möglich?”“Gestern hat es geklappt.”“Das ist noch nie zuvor passiert.”“Das ist komisch …”
“Dies soll in der nächsten Version behoben werden.”“Ja, wir wussten, dass das passieren würde.”“Vielleicht unterstützen wir diese Plattform einfach nicht.”“Es ist eine Funktion. Wir haben die Spezifikationen lediglich nicht aktualisiert.”“Sicherlich wird niemand das Programm auf diese Weise verwenden.”
Die BuxFix Bingo Spielkarte

Übrigens haben auch Entwickler ein solches Spiel. Sie erhalten jedes Mal Punkte, wenn ein QA-Mitarbeiter versucht, einen Defekt an einer Funktion zu melden, die wie angegeben funktioniert.

Die BuxFix Bingo Spielkarte

API 4 Future

Viele Ideen sind auf dem Papier hervorragend. Oft fehlt aber das Wissen wie man brillante Konzepte in den eigenen Alltag einbauen kann. Dieser kleine Workshop soll die Lücke zwischen Theorie und Praxis schließen und zeigt mit welchen Maßnahmen man langfristig zu einer stabile API gelangt.

(c) 2021 Marco Schulz, Java PRO Ausgabe 1, S.31-34

Bei der Entwicklung kommerzieller Software ist vielen Beteiligten oft nicht klar, das die Anwendung für lange Zeit in Benutzung sein wird. Da sich unsere Welt stetig im Wandel befindet, ist es leicht abzusehen, dass im Laufe der Jahre große und kleine Änderungen der Anwendung ausstehen werden. Zu einer richtigen Herausforderung wird das Vorhaben, wenn die zu erweiternde Anwendung nicht für sich isoliert ist, sondern mit anderen Systemkomponenten kommuniziert. Denn das bedeutet für die Konsumenten der eigenen Anwendung in den meisten Fällen, das sie ebenfalls angepasst werden müssen. Ein einzelner Stein wird so schnell zu einer Lawine. Mit einem guten Lawinenschutz lässt sich die Situation dennoch beherrschen. Das gelingt aber nur, wenn man berücksichtigt, das die im nachfolgenden beschriebenen Maßnahmen ausschließlich für eine Prävention gedacht sind. Hat sich die Gewalt aber erst einmal entfesselt, kann ihr kaum noch etwas entgegengesetzt werden. Klären wir deshalb zu erst was eine API ausmacht.

Verhandlungssache

Ein Softwareprojekt besteht aus verschieden Komponenten, denen spezialisierte Aufgaben zuteil werden. Die wichtigsten sind Quelltext, Konfiguration und Persistenz. Wir befassen uns hauptsächlich mit dem Bereich Quelltext. Ich verrate keine Neuigkeiten, wenn ich sage dass stets gegen Interfaces implementiert werden soll. Diese Grundlage bekommt man bereits in der Einführung der Objektorientierten Programmierung vermittelt. Bei meiner täglichen Arbeit sehe ich aber sehr oft, das so manchem Entwickler die Bedeutung der Forderung gegen Interfaces zu Entwickeln, nicht immer ganz klar ist, obwohl bei der Verwendung der Java Standard API, dies die übliche Praxis ist. Das klassische Beispiel hierfür lautet:

List<String> collection = new ArrayList<>();

Diese kurze Zeile nutzt das Interface List, welches als eine ArrayList implementiert wurde. Hier sehen wir auch, das keine Anhängsel in Form eines I die Schnittstelle kennzeichnet. Auch die zugehörige Implementierung trägt kein Impl im Namen. Das ist auch gut so! Besonders bei der Implementierungsklasse könnten ja verschiedene Lösungen erwünscht sein. Dann ist es wichtig diese gut zu kennzeichnen und leicht durch den Namen unterscheidbar zu halten. ListImpl und ListImpl2 sind verständlicherweise nicht so toll wie ArrayList und LinkedList auseinander zu halten. Damit haben wir auch schon den ersten Punk einer stringenten und sprechenden Namenskonvention klären können.

Im nächsten Schritt beschäftigen uns die Programmteile, welche wir möglichst nicht für Konsumenten der Anwendung nach außen geben wollen, da es sich um Hilfsklassen handelt. Ein Teil der Lösung liegt in der Struktur, wie die Packages zu organisieren sind. Ein sehr praktikabler Weg ist:

  • my.package.path.business: enthält sämtliche Interfaces
  • my.package.path.application: enthält die Implementierungen der Interfaces
  • my.package.path.application.hepler: enthält interne Hilfsklassen

Bereits über diese simple Architektur signalisiert man anderen Programmierern, das es keine gute Idee ist Klassen aus dem Package helper zu benutzen. Ab Java 9 gibt es noch weitreichendere Restriktion, das Verwenden interner Hilfsklassen zu unterbinden. Die Modularisierung, welche mit dem Projekt Jingsaw [1] in Java 9 Einzug genommen hat, erlaubt es im Moduldescriptor module-info.java Packages nach außen hin zu verstecken.

Separatisten und ihre Flucht vor der Masse

Schaut man sich die meisten Spezifikationen etwas genauer an, so stellt man fest, das viele Schnittstellen in eigene Bibliotheken ausgelagert wurden. Technologisch betrachtet würde das auf das vorherige Beispiel bezogen bedeuten, dass das Package business welches die Interfaces enthält in eine eigene Bibliothek ausgelagert wird. Die Trennung von API und der zugehörigen Implementierung erlaubt es grundsätzlich Implementierungen leichter gegeneinander auszutauschen. Es gestattet außerdem einem Auftraggeber eine stärkeren Einfluss auf die Umsetzung seines Projektes bei seinem Vertragspartner auszuüben, indem der Hersteller die API durch den Auftraggeber vorgefertigt bekommt. So toll wie die Idee auch ist, damit es dann auch tatsächlich so klappt, wie es ursprünglich gedacht wurde, sind aber ein paar Regeln zu beachten.

Beispiel 1: JDBC. Wir wissen, das die Java Database Connectivity ein Standard ist, um an eine Applikation verschiedenste Datenbanksysteme anbinden zu können. Sehen wir von den Probleme bei der Nutzung von nativem SQL einmal ab, können JDBC Treiber von MySQL nicht ohne weiteres durch postgreSQL oder Oracle ersetzt werden. Schließlich weicht jeder Hersteller bei seiner Implementierung vom Standard mehr oder weniger ab und stellt auch exklusive Funktionalität des eigene Produktes über den Treiber mit zu Verfügung. Entscheidet man sich im eigenen Projekt massiv diese Zusatzfeatures nutzen zu wollen, ist es mit der leichten Austauschbarkeit vorüber.

Beispiel 2: XML. Hier hat man gleich die Wahl zwischen mehreren Standards. Es ist natürlich klar das die APIs von SAX, DOM und StAX nicht zueinander kompatibel sind. Will man beispielsweise wegen einer besseren Performance von DOM zum ereignisbasierten SAX wechseln, kann das unter Umständen umfangreiche Codeänderungen nach sich ziehen.

Beispiel 3: PDF. Zu guter letzt habe ich noch ein Szenario von einem Standard parat, der keinen Standard hat. Das Portable Document Format selbst ist zwar ein Standard wie Dokumentdateien aufgebaut werden, aber bei der Implementierung nutzbarer Programmbibliotheken für die eigene Anwendung, köchelt jeder Hersteller sein eigenes Süppchen.

Die drei kleinen Beispiele zeigen die üblichen Probleme auf die im täglichen Projektgeschäft zu meistern sind. Eine kleine Regel bewirkt schon großes: Nur Fremdbibliotheken nutzen, wenn es wirklich notwendig ist. Schließlich birgt jede verwendete Abhängigkeit auch ein potenzielles Sicherheitsrisiko. Es ist auch nicht notwendig eine Bibliothek von wenigen MB einzubinden um die drei Zeile einzusparen, die benötigt werden um einen String auf leer und null zu prüfen.

Musterknaben

Wenn man sich für eine externe Bibliothek entschieden hat, so ist es immer vorteilhaft sich anfänglich die Arbeit zu machen und die Funktionalität über eine eigene Klasse zu kapseln, welche man dann exzessiv nutzen kann. In meinem persönlichen Projekt TP-CORE auf GitHub [2] habe ich dies an mehreren Stellen getan. Der Logger kapselt die Funktionalität von SLF4J und Logback. Im Vergleich zu den PdfRenderer ist die Signatur der Methoden von den verwendeten Logging Bibliotheken unabhängig und kann somit leichter über eine zentrale Stelle ausgetauscht werden. Um externe Bibliotheken in der eigenen Applikation möglichst zu kapseln, stehen die Entwurfsmuster: Wrapper, Fassade und Proxy zur Verfügung.

Wrapper: auch Adaptor Muster genannt, gehört in die Gruppe der Strukturmuster. Der Wrapper koppelt eine Schnittstelle zu einer anderen, die nicht kompatibel sind.

Fassade: ist ebenfalls ein Strukturmuster und bündelt mehrere Schnittstellen zu einer vereinfachten Schnittstelle.

Proxy: auch Stellvertreter genannt, gehört ebenfalls in die Kategorie der Strukturmuster. Proxies sind eine Verallgemeinerung einer komplexen Schnittstelle. Es kann als Komplementär der Fassade verstanden werden, die mehrere Schnittstellen zu einer einzigen zusammenführt.

Sicher ist es wichtig in der Theorie diese unterschiedlichen Szenarien zu trennen, um sie korrekt beschreiben zu können. In der Praxis ist es aber unkritisch, wenn zur Kapselung externer Funktionalität Mischformen der hier vorgestellten Entwurfsmuster entstehen. Für alle diejenigen die sich intensiver mit Design Pattern auseinander Setzen möchten, dem sei das Buch „Entwurfsmuster von Kopf bis Fuß“ [3] ans Herz gelegt.

Klassentreffen

Ein weiterer Schritt auf dem Weg zu einer stabilen API ist eine ausführliche Dokumentation. Basierend auf den bisher besprochenen Schnittstellen, gibt es eine kleine Bibliothek mit der Methoden basierend der API Version annotiert werden können. Neben Informationen zum Status und der Version, können für Klassen über das Attribute consumers die primäre Implementierungen aufgeführt werden. Um API Gaurdian dem eigenen Projekt zuzufügen sind nur wenige Zeilen der POM hinzuzufügen und die Property ${version} gegen die aktuelle Version zu ersetzen.

  <dependency>
    <groupId>org.apiguardian</groupId>
    <artifactId>apiguardian-api</artifactId>
    <version>${version}</version>
  </dependency>

Die Auszeichnung der Methoden und Klassen ist ebenso leicht. Die Annotation @API hat die Attribute: statussince und consumers. Für Status sind die folgenden Werte möglich:

  • DEPRECATED: Veraltet, sollte nicht weiterverwendet werden.
  • EXPERIMENTAL: Kennzeichnet neue Funktionen, auf die der Hersteller gerne Feedback erhalten würde. Mit Vorsicht verwenden, da hier stets Änderungen erfolgen können.
  • INTERNAL: Nur zur internen Verwendung, kann ohne Vorwarnung entfallen.
  • STABLE: Rückwärts kompatibles Feature, das für die bestehende Major-Version unverändert bleibt.
  • MAINTAINED: Sichert die Rückwärtsstabilität auch für das künftige Major-Release zu.

Nachdem nun sämtliche Interfaces mit diesen nützlichen META Informationen angereichert wurden, stellt sich die Frage wo der Mehrwert zu finden ist. Dazu verweise ich schlicht auf Abbildung 1, welche den Arbeitsalltag demonstriert.

Abbildung 1: Suggestion in Netbeans mit @API Annotation in der JavaDoc

Für Service basierte RESTful APIs, gibt es ein anderes Werkzeug, welches auf den Namen Swagger [4] hört. Auch hier wird der Ansatz aus Annotationen eine API Dokumentation zu erstellen verfolgt. Swagger selbst scannt allerdings Java Webservice Annotationen, anstatt eigene einzuführen. Die Verwendung ist ebenfalls recht leicht umzusetzen. Es ist lediglich das swagger-maven-plugin einzubinden und in der Konfiguration die Packages anzugeben, in denen die Webservices residieren. Anschließend wird bei jedem Build eine Beschreibung in Form einer JSON Datei erstellt, aus der dann Swagger UI eine ausführbare Dokumentation generiert. Swagger UI selbst wiederum ist als Docker Image auf DockerHub [5] verfügbar.

<plugin>
   <groupId>io.swagger.core.v3</groupId>
   <artifactId>swagger-maven-plugin</artifactId>
   <version>${version}</version>
   <configuration>
      <outputFileName>swagger</outputFileName>
      <outputFormat>JSON</outputFormat>
      <resourcePackages>
          <package>org.europa.together.service</package>
      </resourcePackages>
      <outputPath>${project.build.directory}</outputPath>
   </configuration>
</plugin>
Abbildung 2: Swagger UI Dokumentation der TP-ACL RESTful API.

Versionierung ist für APIs ein wichtiger Punkt. Unter Verwendung des Semantic Versioning lässt sich bereits einiges von der Versionsnummer ablesen. Im Bezug auf eine API ist das Major Segment von Bedeutung. Diese erste Ziffer kennzeichnet API Änderungen, die inkompatibel zueinander sind. Eine solche Inkompatibilität ist das Entfernen von Klassen oder Methoden. Aber auch das Ändern bestehender Singnaturen oder der Rückgabewert einer Methode erfordern bei Konsumenten im Rahmen einer Umstellung Anpassungen. Es ist immer eine gute Entscheidung Arbeiten, die Inkompatibilitäten verursachen zu bündeln und eher selten zu veröffentlichen. Dies zeugt von Stabilität im Projekt.

Auch für WebAPIs ist eine Versionierung angeraten. Die geschieht am besten über die URL, in dem eine Versionsnummer eingebaut wird. Bisher habe ich gute Erfahrungen gesammelt, wenn lediglich bei Inkompatibilitäten die Version hochgezählt wird.

Beziehungsstress

Der große Vorteil eines RESTful Service mit „jedem“ gut auszukommen, ist zugleich der größte Fluch. Denn das bedeutet das hier viel Sorgfalt walten muss, da viele Klienten versorgt werden. Da die Schnittstelle eine Ansammlung von URIs darstellt, liegt unser Augenmerk bei den Implementierungsdetails. Dazu nutze ich ein Beispiel aus meinen ebenfalls auf GitHub verfügbaren Projekt TP-ACL.

RolesDO role = rolesDAO.find(roleName);
String json = rolesDAO.serializeAsJson(role);
if (role != null) {
    response = Response.status(Response.Status.OK)
            .type(MediaType.APPLICATION_JSON)
            .entity(json)
            .encoding("UTF-8")
            .build();
} else {
    response = Response.status(Response.Status.NOT_FOUND).build();
}

Der kurze Auszug aus dem try Block der fetchRole Methode die in der Klasse RoleService zu finden ist. Die GET Anfrage liefert für den Fall, das eine Rolle nicht gefunden wird den 404 Fehlercode zurück. Sie ahnen sicherlich schon worauf ich hinaus will.

Bei der Implementierung der einzelnen Aktionen GET, PUT, DELETE etc. einer Resource wie Rolle, genügt es nicht einfach nur den sogenannten HappyPath umzusetzen. Bereits während des Entwurfes sollte berücksichtigt werden, welche Stadien eine solche Aktion annehmen kann. Für die Implementierung eines Konsumenten (Client) ist es schon ein beachtlicher Unterschied ob eine Anfrage, die nicht mit 200 abgeschlossen werden kann gescheitert ist, weil die Ressource nicht existiert (404) oder weil der Zugriff verweigert wurde (403). Hier möchte ich an die vielsagende Windows Meldung mit dem unerwarteten Fehler anspielen.

Fazit

Wenn wir von eine API sprechen, dann bedeutet es, das es sich um eine Schnittstelle handelt, die von anderen Programmen genutzt werden kann. Der Wechsel eine Major Version indiziert Konsumenten der API, das Inkompatibilität zur vorherigen Version vorhanden ist. Weswegen möglicherweise Anpassungen erforderlich sind. Dabei ist es völlig irrelevant um welche Art API es sich handelt oder ob die Verwendung der Anwendung öffentlich beziehungsweise fetchRole Methode, die Unternehmensintern ist. Die daraus resultierenden Konsequenzen sind identisch. Aus diesem Grund sollte man sich mit den nach außen sichtbaren Bereichen seiner Anwendung gewissenhaft auseinandersetzen.

Arbeiten, welche zu einer API Inkompatibilität führen, sollten durch das Release Management gebündelt werden und möglichst nicht mehr als einmal pro Jahr veröffentlicht werden. Auch an dieser Stelle zeigt sich wie wichtig regelmäßige Codeinspektionen für eine stringente Qualität sind.

Resourcen

Abonnement / Subscription

[English] This content is only available to subscribers.

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

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

Abonnement / Subscription

[English] This content is only available to subscribers.

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


Versionsnummern Anti-Patterns

Nachdem die Gang Of Four (GOF) Erich Gamma, Richard Helm, Ralph Johnson und John Vlissides das Buch Design Patterns: Elements of Reusable Object-Oriented Software (Elemente wiederverwendbarer objektorientierter Software), wurde das Erlernen der Beschreibung von Problemmustern und deren Lösungen in fast allen Bereichen der Softwareentwicklung populär. Ebenso populär wurde das Erlernen der Beschreibung von Don’ts und Anti-Patterns.

In Publikationen, die sich mit den Konzepten der Entwurfsmuster und Anti-Pattern befassen, finden wir hilfreiche Empfehlungen für Softwaredesign, Projektmanagement, Konfigurationsmanagement und vieles mehr. In diesem Artikel möchte ich meine Erfahrungen im Umgang mit Versionsnummern für Software-Artefakte weitergeben.

Die meisten von uns sind bereits mit einer Methode namens semantische Versionierung vertraut, einem leistungsstarken und leicht zu erlernenden Regelwerk dafür, wie Versionsnummern strukturiert sein sollten und wie die einzelnen Segmente zu inkrementieren sind.

Beispiel für eine Versionsnummerierung:

  • Major: Inkompatible API-Änderungen.
  • Minor: Hinzufügen neuer Funktionen.
  • Patch: Fehlerbehebungen und Korrekturen.
  • Label: SNAPSHOT zur Kennzeichnung des Status “in Entwicklung”.

Eine inkompatible API-Änderung liegt dann vor, wenn eine von außen zugängliche Funktion oder Klasse gelöscht oder umbenannt wurde. Eine andere Möglichkeit ist eine Änderung der Signatur einer Methode. Das bedeutet, dass der Rückgabewert oder die Parameter gegenüber der ursprünglichen Implementierung geändert wurden. In diesen Fällen ist es notwendig, das Major-Segment der Versionsnummer zu erhöhen. Diese Änderungen stellen für API-Kunden ein hohes Risiko dar, da sie ihren eigenen Code anpassen müssen.

Beim Umgang mit Versionsnummern ist es auch wichtig zu wissen, dass 1.0.0 und 1.0 gleichwertig sind. Dies hat mit der Anforderung zu tun, dass die Versionen einer Softwareversion eindeutig sein müssen. Wenn dies nicht der Fall ist, ist es unmöglich, zwischen Artefakten zu unterscheiden. In meiner beruflichen Praxis war ich mehrfach an Projekten beteiligt, bei denen es keine klar definierten Prozesse für die Erstellung von Versionsnummern gab. Dies hatte zur Folge, dass das Team die Qualität des Artefakts sicherstellen musste und sich nicht mehr sicher war, mit welcher Version des Artefakts es sich gerade befasste.

Der größte Fehler, den ich je gesehen habe, war die Speicherung der Version eines Artefakts in einer Datenbank zusammen mit anderen Konfigurationseinträgen. Die korrekte Vorgehensweise sollte sein: die Version innerhalb des Artefakts so zu platzieren, dass niemand nach einem Release diese von außen ändern kann. Die Falle, in die man sonst tappt, ist der Prozess, wie man die Version nach einem Release oder Neuinstallation aktualisiert.

Vielleicht haben Sie eine Checkliste für alle manuellen Tätigkeiten während eines Release. Aber was passiert, nachdem eine Version in einer Testphase installiert wurde und aus irgendeinem Grund eine andere Version der Anwendung eneut installiert werden muss? Ist Ihnen noch bewusst, dass Sie die Versionsnummer manuell in der Datenbank ändern müssen? Wie finden Sie heraus, welche Version installiert ist, wenn die Informationen in der Datenbank nicht stimmen?

Die richtige Version in dieser Situation zu finden, ist eine sehr schwierige Aufgabe. Aus diesem Grund haben gibt es die Anforderung, die Version innerhalb der Anwendung zu halten. Im nächsten Schritt werden wir einen sicheren und einfachen Weg aufzeigen, wie man dieses Problem voll automatisiert lösen kann.

Die Voraussetzung ist eine einfache Java-Bibliothek die mit Maven gebaut wird. Standardmäßig wird die Versionsnummer des Artefakts in der POM notiert. Nach dem Build-Prozess wird unser Artefakt erstellt und wie folgt benannt: artifact-1.0.jar oder ähnlich. Solange wir das Artefakt nicht umbenennen, haben wir eine gute Möglichkeit, die Versionen zu unterscheiden. Selbst nach einer Umbenennung kann mit einem einfachen Trick nach einem Unzip des Archives im META-INF-Ordner der richtige Wert gefunden werden.

Wenn Sie die Version in einer Poroperty oder Klasse fest einkodiert haben, würde das auch funktionieren, solange Sie nicht vergessen diese immer aktuell zu halten. Vielleicht müssen Sie dem Branching und Merging in SCM Systemen wie Git besondere Aufmerksamkeit schenken, um immer die korrekte Version in Ihrer Codebasis zu haben.

Eine andere Lösung ist die Verwendung von Maven und dem Tokenreplacement. Bevor Sie dies in Ihrer IDE ausprobieren, sollten Sie bedenken, dass Maven zwei verschiedene Ordner verwendet: Sources und Ressourcen. Die Token-Ersetzung in den Quellen wird nicht richtig funktionieren. Nach einem ersten Durchlauf ist Ihre Variable durch eine feste Zahl ersetzt und verschwunden. Ein zweiter Durchlauf wird daher fehlschlagen. Um Ihren Code für die Token-Ersetzung vorzubereiten, müssen Sie Maven als erstes im Build-Lifecycle konfigurieren:

<build>
   <resources>
      <resource>
         <directory>src/main/resources/</directory>
         <filtering>true</filtering>
      </resource>
   </resources>
   <testResources>
      <testResource>
         <directory>src/test/resources/</directory>
         <filtering>true</filtering>
      </testResource>
   </testResources>
</build>

Nach diesem Schritt müssen Sie die Property ${project.version} aus dem POM kennen. Damit können Sie eine Datei mit dem Namen version.property im Verzeichnis resources erstellen. Der Inhalt dieser Datei besteht nur aus einer Zeile: version=${project.version}. Nach einem Build finden Sie in Ihrem Artefakt die version.property mit der gleichen Versionsnummer, die Sie in Ihrem POM verwendet haben. Nun können Sie eine Funktion schreiben, die die Datei liest und diese Property verwendet. Sie können das Ergebnis zum Beispiel in einer Konstante speichern, um es in Ihrem Programm zu verwenden. Das ist alles, was Sie tun müssen!

Beispiel: https://github.com/ElmarDott/TP-CORE/blob/master/src/main/java/org/europa/together/utils/Constraints.java

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 nach programmieren 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 ausfiel. 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. Lasst 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

Versionsverwaltung mit Expressions

m Umgang mit Source-Control-Management-Systemen (SCM) wie Git oder Subversion haben sich im Lauf der Zeit vielerlei Praktiken bewährt. Neben unzähligen Beiträgen über Workflows zum Branchen und Mergen ist auch das Formulieren verständlicher Beschreibungen in den Commit-Messages ein wichtiges Thema.

(c) 2018 Marco Schulz, Java PRO Ausgabe 3, S.50-51

Ab und zu kommt es vor, dass in kollaborativen Teams vereinzelte Code-Änderungen zurückgenommen werden müssen. So vielfältig die Gründe für ein Rollback auch sein mögen, das Identifizieren betroffener Code-Fragmente kann eine beachtliche Herausforderung sein. Die Möglichkeit jeder Änderung des Code-Repository eine Beschreibung anzufügen, erleichtert die Navigation zwischen den Änderungen. Sind die hinterlegten Kommentare der Entwickler dann so aussagekräftig wie „Layout-Anpassungen“ oder „Tests hinzugefügt“, hilft dies wenig weiter. Diese Ansicht vertreten auch diverse Blog-Beiträge [siehe Weitere Links] und sehen das Formulieren klarer Commit-Messages als wichtiges Instrument, um die interne Kommunikation zwischen einzelnen Team-Mitgliedern deutlich zu verbessern.

Das man als Entwickler nach vollbrachter Arbeit nicht immer den optimalen Ausdruck findet, seine Aktivitäten deutlich zu formulieren, kann einem hohen Termindruck geschuldet sein. Ein hilfreiches Instrument, ein aussagekräftiges Resümee der eigenen Arbeit zu ziehen, ist die nachfolgend vorgeschlagene Struktur und ein darauf operierendes aussagekräftiges Vokabular inklusive einer festgelegten Notation. Die vorgestellte Lösung lässt sich sehr leicht in die eigenen Prozesse einfügen und kann ohne großen Aufwand erweitert bzw. angepasst werden.

Mit den standardisierten Expressions besteht auch die Möglichkeit die vorhandenen Commit-Messages automatisiert zu Parsen, um die Projektevolution gegebenenfalls grafisch darzustellen. Sämtliche Einzelheiten der hier vorgestellten Methode sind in einem Cheat-Sheet auf einer Seite übersichtlich zusammengefasst und können so leicht im Team verbreitet werden. Das diesem Text zugrundeliegende Paper ist auf Research-Gate [1] in englischer Sprache frei verfügbar.

Eine Commit-Message besteht aus einer verpflichtenden (mandatory) ersten Zeile, die sich aus der Funktions-ID, einem Label und der Spezifikation zusammensetzt. Die zweite und dritte Zeile ist optional. Die Task-ID, die Issue-Management-Systeme wie Jira vergeben, wird in der zweiten Zeile notiert. Grund dafür ist, dass nicht jedes Projekt an ein Issue-Management-System gekoppelt ist. Viel wichtiger ist auch die Tatsache, dass Funktionen meist auf mehrere Tasks verteilt werden. Eine Suche nach der Funktions-ID fördert alle Teile einer Funktionalität zu tage, auch wenn dies unterschiedlichen Task-IDs zugeordnet ist. Die ausführliche Beschreibung in Zeile drei ist ebenfalls optional und rückt auf Zeile zwei vor, falls keine Task-ID notiert wird. Das gesamte Vokabular zu dem nachfolgenden Beispiel ist im Cheat-Sheet notiert und soll an dieser Stelle nicht wiederholt werden.

[CM-05] #CHANGE ’function:pom’
<QS-0815>
{Change version number of the dependency JUnit from 4 to 5.0.2}

Projektübergreifende Aufgaben wie das Anpassen der Build-Logik, Erzeugen eines Releases oder das Initiieren eines Repositories können in allgemeingültigen Funktions-IDs zusammengefasst werden. Entsprechende Beispiele sind im Cheat-Sheet angeführt.

Configuration Management
[CM-00] #INIT, #REVIEW, #BRANCH, #MERGE, #RELEASE #BUILD-MNGT

Möchte man nun den Projektfortschritt ermitteln, ist es sinnvoll aussagekräftige Meilensteine miteinander zu vergleichen. Solche Punkte (POI) stellen üblicherweise Releases dar. So können bei Berücksichtigung des Standard-Release-Prozesses und des Semantic-Versionings Metriken über die Anzahl der Bug-Fixes pro Release erstellt werden. Aber auch klassische Erhebungen wie Lines-of-Code zwischen zwei Minor-Releases können interessante Erkenntnisse fördern.

Resourcen

Faktor Mensch! – wiederholbare Projekterfolge mit SCRUM

Zu der Erkenntnis, dass Menschen Projekte machen, gelangt man nicht erst durch die Lektüre von Tom De Marcos Büchern. Aber was hat sich in den letzten Jahrzehnten tatsächlich in der professionellen Software Entwicklung getan? Trotz der vielen neuen Innovationen und Methodiken hat sich augenscheinlich nur wenig bewegt. Die Klagelieder aus den Unternehmen summen nach wie vor die gleiche Melodie.

(c) 2017 Marco Schulz, Java PRO Ausgabe 2, S.51-53

Stellen wir uns bei all dem Wandel einmal eine essentielle Frage: Kann ein Softwareprojekt heute noch erfolgreich sein, wenn es nicht auf Methoden wie Scrum setzt oder die neuesten Innovationen verwendet? Anwendungen werden Dank leistungsfähigerer Maschinen zunehmend komplexer, so dass diese nicht mehr von einzelnen Personen in ihrer Gänze überblickt werden können. Das gute Teamarbeit ein wichtiger Bestandteil erfolgreicher Projekte ist, ist seit langem auch bei den Unternehmen angekommen. Daher zählen bei Bewerbungsgesprächen mittlerweile nicht allein harte technische Fähigkeiten. Auch ausgewogene Softskills und Kommunikationsfähigkeit sind wichtige Anforderungen bei der Auswahl von neuem Personal. Daher die provokante Behauptung, dass andere Faktoren für Projekterfolge wesentlich essentieller sind als technologische Details.

Alter Wein in neuen Schläuchen?

Ganz so einfach ist es dann doch nicht. Und nicht alles Neue macht der Mai. Aus persönlicher Erfahrung wiederholt sich die Geschichte kontinuierlich, lediglich die Protagonisten können ausgetauscht werden. Stellen wir die klassischen Modelle in einen Vergleich mit agilen Techniken, können wir nur wenige essentielle Unterschiede ausmachen. Die einzelnen Stufen wie Planung, Implementierung, Testen und Ausliefern sind wenig variabel. Ob man nun den Projektleiter als Scrum-Master bezeichnet oder Releases lieber als Sprints definiert, ist Geschmackssache. Allein ein neues Vokabular genügt allerdings nicht, um von tatsächlicher Innovation zu sprechen. Ein neues Vokabular hilft aber durchaus, sich leichter von alten und möglicherweise schlechten Gewohnheiten zu lösen. Der Ansatz von Scrum ist es, das Kommunikationsproblem in Teams zu adressieren und durch Techniken aus der Rhetorik, die gemeinsamen Ziele zu visualisieren. Kurze Entwicklungszyklen ermöglichen ein schnelles Feedback um mögliche Probleme bereits zu Beginn zu erkennen und berichtigen zu können. Auf tatsächliche Bedürfnisse zügig zu reagieren sind Kernkompetenzen eines Managers. Analysiert man in einer Retrospektive was zu Fehleinschätzungen beim Management geführt hat, ist es nicht selten die mangelnde Bereitschaft sich mit technischen Zusammenhängen auseinandersetzen zu wollen. Dies ist aber essentiell, für ein Gelingen der anvisierten Ziele. Klare Anweisungen lassen sich nur dann formulieren, wenn man deren Inhalt auch versteht. Ein sehr empfehlenswerter Titel für IT Management ist von Johanna Rothman und Esther Derby „Behind closed Doors“ welches hervorragend Motivierung, Teamentwicklung und Kommunikation bespricht.

Werfen wir einmal ein Blick in ein typisches Auftaktmeeting, wenn ein neues Projekt initiiert wird. Oft ist an dieser Stelle noch keine klare Vision vorhanden. Das wiederum hat zur Folge das schwammige Anforderungen formuliert werden. Sehr klassisch ist bei nicht funktionalen Anforderungen, dass sich alle Beteiligten einig sind, dass beispielsweise eine hohe Qualität eingehalten werden muss. Es wir schnell vergessen zu definieren, was man unter Qualität versteht und wie man dies erreichen will. Lenkt man in diesen Meetings alle Beteiligten auf die Details, fehlt oft die Bereitschaft sich diesen mit der notwendigen Sorgfalt zuzuwenden. Euphorisch benennt man fix einen Qualitätsverantwortlichen, ohne ihm die notwendige Entscheidungsgewalt zuzusprechen. Zum Thema Qualität hat sich sehr ausführlich bereits im Jahre 1976 B. W. Boehm auf knapp 14 Seiten geäußert. Eine Lösung für dieses Problem wäre es, sich zu entschließen einen hohen Wert auf Coding-Standarts zu legen. Diese Konvention ermöglicht es den einzelnen Entwicklern sich schnell in die Lösungen der Kollegen einzufinden. Es gewährleistet nicht, das die Applikation robust gegen Änderungen ist und diese über einen langen Zeitraum auch wartungsfähig bleibt. Eine Entscheidung alle diese Aspekte zu bedienen hat die Konsequenz, dass damit auch die bereitzustellenden Aufwände erhöht werden müssen. Von daher gilt es, bewusst abzuwägen was tatsächlich notwendig ist. Aber verweilen wir nicht allzu lange beim Management. Es gibt viele weitere Dinge die es lohnt ein wenig stärker auszuleuchten.

Im Gleichschritt Marsch!

Nicht alle Arbeiten zählen zu den begehrtesten Beschäftigungen, dennoch müssen sie erledigt werden. Eine gute Unterstützung findet man für solche Tätigkeiten in Automatisierungsmechanismen. Dazu muss man sich auch bewusst sein, dass eine automatisierte Lösung bei komplexen Problemen sehr aufwendig gestaltet werden kann. Die damit verbundenen Kosten können sich erst dadurch amortisieren, dass die gefundene Lösung sehr häufig eingesetzt wird oder die Anfälligkeiten für Fehler während der Ausführung massiv reduziert werden. Ein hervorragendes Beispiel für diese Thematik sind Build- und Testprozesse. Nicht das Werkzeug bestimmt das Ergebnis, sondern der Prozess definiert das zu verwendende Werkzeug. Auch an dieser Stelle überschätzt sich der Mensch hin und wieder, in dem er hochkomplexe Prozesse nicht in ihre Bestandteile zerlegt, um diese dann nacheinander abzuarbeiten. Schlägt dann ein Schritt fehl ist nur dieser Teilprozess zu wiederholen. Hierzu gab es, in unterschiedlichen persönlich erlebten Situationen des Autors, ähnliche Begebenheiten. Es war notwendig die Aussage zu entkräften, weswegen es sich bei der Wahl explizit gegen Maven und bewusst für Gradle entschieden werden sollte. Das Argument für Gradle war die Möglichkeit eines frei choreographierbaren Buil-Prozesses und die damit verbundene Flexibilität. Die Notwendigkeit einer Build-Choreographie kann ein wichtiger Indikator für eine mangelhafte Architektur sein. Fehlende Kapselung und dadurch implizierte Abhängigkeiten sind die üblichen Verdächtigen. Die strikten Konventionen von Maven reduzieren hingegen das Aufkommen von unlesbaren Build-Skripten, die kaum oder nur mit erheblichem Aufwand gewartet werden können. Es ist nicht immer förderlich, volles Vertrauen an die Verantwortlichen zu delegieren, in der Absicht, dass diese optimale Ergebnisse produzieren. Zuviel Freiheit führt auch schnell zu Anarchie. In diesem Zusammenhang wäre das Argument für die Verwendung von Gradle, bereits einen Experten für diese Technologie im Hause zu haben, so schwergewichtig, dass wenig Spielräume für eine andere Wahl offen stünden.

Auch die Erstellung von Testfällen ist ein Kapitel für sich. Es grenzt schon an ein Wunder, wenn überhaupt Testfälle existieren. Wenn diese dann auch noch eine hohe Testabdeckung erzielen, könnte man meinen einen Großteil möglicher Risiken minimiert zu haben. Dass Testen nicht gleich Testen ist, skizziert die folgende Überlegung: Sehr wichtig ist zu wissen, dass das Bestehen der Testfälle keine Fehlerfreiheit garantiert. Es wird lediglich garantiert, dass die Anwendung sich entsprechend den Vorgaben der Testfälle verhält. Hierzu ist es interessant zu wissen, dass für IT-Projekte der NASA sämtliche Compiler-Meldungen für selbst entwickelte Software, die sich in Produktion befindet, behoben sein müssen. Aber auch die Aussagekraft von Testfällen lässt sich etwas ausführlicher betrachten. Die zyklomatische Komplexität nach McCabe gibt einen guten Hinweis, wie viele Testfälle für eine Methode benötigt werden. Veranschaulichen wir die Zusammenhänge an einem kleinen Beispiel. Ein Validator prüft anhand eines regulären Ausdrucks (Regex) mit der Methode validate(), ob es sich bei der Benutzereingabe um ein korrektes 24-Stunden-Format der Uhrzeit handelt. Dabei werden ausschließlich die Stunden und Minuten in zweistelliger Notation (hh:mm) angenommen. Es besteht nun die Möglichkeit einen einzigen Testfall für den regulären Ausdruck der Uhrzeit zu schreiben. Schlägt dieser Test fehl, muss der Entwickler den vorhandenen Testfall analysieren um das Problem zu identifizieren. Genauso wenig sagt die Methode testUhrzeit24hFormat() über die tatsächlichen durchgeführten Tests etwas aus. So hat man möglicherweise nicht immer im Fokus, dass Werte wie 24:00 oder 00:60 unzulässig sind, hingegen 00:00 und 23:59 gültige Einträge darstellen. Splittet man den Testfall beispielsweise in die Teile testMinuten und testStunden, so erkennt man schnell die tatsächlichen Schranken. Dieser Formalismus gestattet es zudem fehlgeschlagene Testfälle schneller bewerten zu können. Die Kombination mit dem Framework jGiven ermöglicht es deskriptive Testszenarien zu formulieren, sodass nachgelagerte manuelle Akzeptanztest weniger aufwendig gestaltet werden müssen.

Wir messen, weil wir können

Die Vermessung der Welt ist nicht allein den rein physikalischen Größen vorbehalten. Auch für Softwareprojekte bilden Metriken eine nützliche Informationsquelle. Wie bereits erläutert ist die zyklomatische Komplexität ein guter Anhaltspunkt für die Bewertung von Testfällen. Auch die klassischen Lines-of-Code (LoC) sagen einiges über die Größe eines Projektes aus. Was bei all dem Zahlenwerk oft wenig beachtet wird, sind die tatsächlichen Points-of-Intrests (PoI). Sicher kann man Äpfel mit Birnen vergleichen. Aber der Nutzen bleibt etwas fragwürdig wenn man keinen geeigneten Kontext definiert. Auch an dieser Stelle ist es wichtig sich nicht mit einer Informationsflut an Daten zu überfordern. So ist es hilfreich, die Projektentwicklung der einzelnen Release Milestones zu dokumentieren und dann zu vergleichen. Auch die Vergleichbarkeit unterschiedlicher Projekte führt zu neuen Erkenntnissen. Dabei ist es aber nicht förderlich ein Projekt, welches bereits 10 Jahre Entwicklung beschritten hat, mit einer kleinen Hilfsbibliothek zu vergleichen. Auch die Repräsentation der ermittelten Informationen ist ein nicht zu vernachlässigendes Detail. Eine grafische Darstellung lässt die Zusammenhänge leichter fassen. So ist die reine Darstellung der LoC als nackte Zahl nett zu wissen, aber eine Bewertung gestaltet sich auf diese Weise eher schwer. Ein kumulierter Chart über die Entwicklung der LoC zu den einzelnen Releases vermittelt dagegen ein recht deutliches Bild. Dies lässt sich weiter befüllen mit der Anzahl der Klassen, Interfaces, Packages und JavaDocs und all dies in Relation zur Speichergröße des fertigen Artefaktes zu setzen. Der Einsatz hochkomplexer Werkzeuge kann durch ein geeignetes Tabellenkalkulationsprogramm und Methoden des Projekt-Controllings ohne weiteres ersetzt werden. Ein Skript, das die notwendigen Rohdaten einsammelt, kann von der Entwicklungsabteilung schnell bereitgestellt werden ohne, dass ein überfrachteter Werkzeugkasten den man mit sich herum tragen muss, zu „schweren Rückenproblemen“ führt.

Informationsdschungel

Ein weiterer Blick in den Werkzeugkasten bringt nicht selten verstaubte Infrastruktur zutage, die den Anschein erweckt als reiner Selbstzweck zu fungieren. Das Unternehmens-Wiki, bei dem die meisten Einträge aus weniger als 100 Zeichen bestehen sowie eine Navigation nur vermutet werden kann, ist leider die traurige die Regel. Aussagen zum Daily-Meeting wie „Ich bin Heiko und kümmere mich auch heute wieder um die Suchfunktion“ erinnern eher an eine Selbsthilfegruppe. Das Ganze wird dann noch durch SCM-Logeinträge (SCM ist ein Tool zur Kommentierung von Issues) wie „JIRA-KM-100 update Build-Skripte“ dekoriert. Gute Kommunikation ist mehr als sich seinen Mitmenschen mitzuteilen. Reflektierte Aussagen unterstützen uns bei der Bewältigung unserer täglichen Aufgaben. Sie strukturieren zugleich unser Denken. Wenn wir beim morgendlichen Treffen mit den Kollegen hingegen sagen „Für das Erzeugen des Suchindexes implementiere ich heute die Abfragen über die Keywords in den Content-Tabellen, sodass ich morgen bereits einige Testfälle formulieren kann“, kurz und auf den Punkt gebracht, dann sind die Kollegen informiert. Ein präziser Kommentar im SCM „JIRAKM-100 Hinzufügen der Lucene-Abhängigkeiten für die Suche“ gibt schnell Aufschluss über die vorgenommenen Arbeiten ohne, dass man erst den entsprechenden Task im Issue-Managment öffnen muss, um zu sehen welche Änderungen vorgenommen wurden. Bereits diese kleinen Aufmerksamkeiten in unserer Kommunikation bewirken einen enormen Anschub in die Motivation des gesamten Teams. Jeder einzelne empfindet sich so wesentlich mehr wertgeschätzt. Funktionierende und aktuelle Anleitungen über das Einrichten des Arbeitsplatzes, Hinweise mit Beispielen zum Schreiben von Kommentaren für SCM-Commits regen die Kollegen zum Mitmachen an. Der Mehrwert einer solchen Unternehmenskultur beschränkt sich nicht einzig auf einen funktionierenden Informationsaustausch. Das höhere Ziel dieser Bestrebungen ist auf eine angenehme Weise, die Produktivität zu steigern, ohne stetig Druck ausüben zu müssen.

Lessons Learned

Wie wir sehen konnten, genügt es nicht sich allein auf eine gute Methodik wie Scrum zu verlassen, um sich von den notwendigen Vorbereitungen befreien zu können. Der Wille allein, etwas Hervorragendes zu erschaffen, ist nicht ausschlaggebend für beste Resultate. Vor den Erfolg ist stets Fleiß zu setzen. Bevor man sich in Details verliert ist es unerlässlich, das große Ganze sehen zu können. Erst wenn alle Beteiligten die gleiche Vision teilen, können sie gemeinsam in die Mission starten. Anhand der beschriebenen Beispiele kann man gut nachvollziehen, dass die vielen neuen Techniken erhebliche Möglichkeiten bieten. Diese Chancen lassen sich allerdings nur dann nutzen, wenn man zuerst die notwendigen Grundlagen tief verinnerlicht hat.

Links & Literatur:

Abonnement / Subscription

[English] This content is only available to subscribers.

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

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.

PHP meets Maven

[Teil 1] [Teil 2] [Teil 3] [Teil 4]

Wikipedia liefert für den Begriff Maven folgende Erklärung: »Ein Maven ist ein Experte, der andere berät und deren Entscheidungen beeinflusst«. Wegen seiner Bedeutung wurde der Begriff Maven für die Namensgebung der Software auserkoren. Jason van Zyl, Gründer und CTO von Sonatype, beschreibt das Programm mit folgenden Worten: »Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project’s build, reporting and documentation from a central piece of information.«

Maven ist ein in Java geschriebenes plattformunabhängiges Projektmanagement-Tool. Es ist ein Open-Source-Projekt der Apache Software Foundation und frei erhältlich. In der Version 2 wurde das Programm völlig neu entwickelt. Das ist auch ein Grund dafür, dass Erweiterungen der Version 2 nicht abwärtskompatibel sind. Derzeit ist die Version 3 aktuell, welche auch mit Maven-2-Projekten kompatibel ist.

Wie bereits angedeutet, handelt es sich bei Maven um ein schlankes Werkzeug, das durch seinen modularen Aufbau problemlos durch eigene Plug-ins erweitert werden kann. Diese Möglichkeit nutzt das Projekt Maven for PHP und stellt eigene Erweiterungen für PHP bereit.

Bild 1: Homepage des Projekts Maven for PHP

Bevor wir nun mit der Installation der Software beginnen, ist es notwendig, etwas über das Konzept von Maven zu erfahren, da dieses Werkzeug mächtiger ist als sein Pendant Ant.

Maven erzeugt aus Java-Quellcode Binärdateien. Die hohe Akzeptanz erreichte das Tool aber durch das transitive Auflösen von Abhängigkeiten zu anderen Softwarebibliotheken. Im Maven-Jargon werden Bibliotheken oder Module als Artefakt bezeichnet. Das Verwalten von Artefakten ist allerdings nur ein kleiner, wenn auch sehr maßgeblicher Aspekt für den Einsatz in PHP-Projekten.

Nicht ohne Grund stellt Maven an sich selbst den Anspruch, ein Projekt-Management-Werkzeug zu sein. Im Projektalltag wird zwischen drei verschiedenen Einsatzbereichen unterschieden. Der umfangreichste Teil ist der Build-Life-cycle mit seinen 21 Unterschritten, die als Phase bezeichnet werden. Die Teilbereiche einer Phase werden wiederum als Goal bezeichnet. So erreicht man eine feingranulare Struktur, in die sich leicht eigene Funktionen einbringen lassen. Ein anderer Aspekt ist die Reporting-Engine, die ihre Arbeit unter dem Site-Lifecycle verrichtet. Für das Aufräumen nach dem vollendeten Werk ist der Clean-Lifecycle zuständig. Was es mit den einzelnen Lifecycles auf sich hat wird an späterer Stelle noch detaillierter geklärt.

Zentrale Steuereinheit

Im Wurzelverzeichnis eines Projekts liegt die zentrale Steuereinheit. Es handelt sich dabei um eine einfache XML-Datei mit dem Namen pom.xml, in der die gesamte Konfiguration des Projekts vorgehalten wird. Die Bezeichnung POM steht im Übrigen für Project Object Model. Bei umfangreichen Projekten kann diese Datei schnell eine beachtliche Größe erlangen. Aus diesem Grund verfolgt Maven das Prinzip »Don’t repeat yourself« (DRY) und »Convention over Configura tion« (COC). Das besagt, es müssen lediglich die Dinge in der POM-Datei eingetragen werden, die vom vorgegeben Standard abweichen. Um den Überblick auch zu einem späteren Zeitpunkt nicht zu verlieren, ist es sehr ratsam, nur in absoluten Ausnahmefällen vom Standard abzuweichen.

Nachdem Sie nun die wichtigsten Begriffe kennen, können wir zur ersten Tat schreiten und die Software installieren.

Schnell installierte Basis

Bild 2: Einstellungen der Umgebungs­variablen unter Windows

Für Maven existiert keine Installationsroutine, wie sie beispielsweise in Windows-Systemen üblich ist. Da das Programm in Java geschrieben ist, muss ein aktuelles Java-SDK auf dem System bereits vorhanden sein. Nach dem erfolgreichem Download und dem anschließenden Entpacken des Archivs sind folgende Schritte auszuführen:

  • Setzen der Umgebungsvariablen JAVA_HOME = {install.java},
  • Setzen der Umgebungsvariablen M2_HOME = {install.maven},
  • Erweitern der PATH-Variable %M2_HOME%\ bin und %JAVA_HOME%\bin.

Mit {install.maven} ist der Ort des ausgepackten Maven-Archivs gemeint. Unter Windows 7 ist die Einstellung der Umgebungsvariablen über die Systemsteuerung hinter der Option System versteckt, die sich dort über den Punkt Erweiterte Systemeinstellungen öffnen lässt. Bei geglückter Installation quittiert Maven die Konsolenausgabe für mvn -vers

Bild 3: Ausgabe der Konsole bei erfolg­reicher Maven-Installation

Dependency Management

Bild 4: Auszug aus einem lokalen Repository

Wie Sie bei der Installation bemerkt haben, ist der Kern von Maven recht kompakt. Die umfangreichen Funktionen werden durch Erweiterungen über die Plug-in-Schnittstelle realisiert. Soll beispielsweise eine Dokumentation mit der Anweisung mvn site erzeugt werden, holt sich Maven die notwendigen Artefakte über das Internet und speichert diese auf dem Rechner in einem lokalen Repository. Die Dateien sind im Home-Verzeichnis des aktuellen Benutzers unter .m2/repository/ zu finden. Wenn man sich die Ordnerstruktur aus Bild 4 ein wenig genauer ansieht, kann man erkennen, dass Maven die Artefakte nach Namen und Versionsnummer organisiert. In dem Screenshot sind im lokalen Repository für das Test-Framework JUnit vier unterschiedliche Versionen mit der dazugehörigen POM-Datei hinterlegt. Anhand des POM ist Maven nun in der Lage, die notwendigen Abhängigkeiten von JUnit ebenfalls aufzulösen. Die Archivierung der Versionen eines Artefakts ermöglicht es später, in einem Projekt innerhalb kürzester Zeit für eine Bibliothek die neueste Version auszuprobieren und im Fall einer Inkompatibilität die Änderung in wenigen Augenblicken wieder rückgängig zu machen. Es muss lediglich in der POM-Datei die Versionsnummer des Artefakts geändert werden.

Ein weiterer Vorteil ist, dass im Konfigurationsmanagement die verwendeten Artefakte nicht mehr archiviert werden müssen. Diese Arbeit übernimmt nun künftig in zuverlässiger Weise Maven. Dank dieses Umstands werden im Konfigurationsmanagement einige MByte an Speicher eingespart, was bei größeren Projekten mit vielen Artefakten einiges an Zeit beim Checkout einsparen kann. Eine Entlastung des Netzwerks ist eine weitere angenehme Randerscheinung.

Nun stellt sich berechtigterweise die Frage, von welchem Server Maven die benötigten Artefakte beziehen kann? Neben dem standardmäßig eingestelltem Remote-Repository repo1.maven.org können auch andere Repositories hinzugefügt werden. Dazu ist die Maven-Installation über die Datei settings.xml den eigenen Bedürfnissen anpassen. Hierbei können zwei Stufen genutzt werden:

  • User Level: Im Home-Directory des aktuellen Nutzers legt Maven den Ordner .m2 an, in dem die settings.xml zu finden ist. Dies ist vor allem im Mehrbenutzerbetrieb nützlich, da hier Passwörter für Logins et cetera hinterlegt werden können.
  • Global Level: Die Datei settings.xml ist in diesem Fall im Ordner conf der Maven-Installation abgelegt. Diese Konfiguration gilt für alle Nutzer auf einem System.

Die Konfiguration über die settings.xml ist projektübergreifend und enthält beispielsweise Einträge für das Login zum Versionskontrollsystem (SCM), den Pfad zum lokalen Repository beziehungsweise zu weiteren Remote-Repositories. Um PHP Maven nutzen zu können, muss das öffentliche Repository in einer der beiden Settings-Dateien eingetragen werden. Listing 1 enthält die hierfür notwendige Konfiguration.

Der Codeblock aus dem Listing ist in einer der settings.xml-Dateien unterhalb der Ebene des Root-Elements einzutragen. Die eigentliche Konfiguration befindet sich im Profil mit der ID profile-php-maven, welches auch als aktiv registriert ist. Es ist ohne Weiteres möglich, mehrere Profile in der Konfiguration aktiv zu setzen, wenn dies notwendig sein sollte. Im Profil werden die verschiedenen Remote-Repositories für PHP Maven registriert. Mit diesen Einträgen ist Maven nun in der Lage, die notwendigen Artefakte aus dem öffentlichen Repository zu laden.

<activeProfiles>
    <activeProfile>profile-php-maven</activeProfile>
</activeProfiles>

<profiles>
	<profile>
	<id>profile-php-maven</id>
	<pluginRepositories>
		<pluginRepository>
			<id>release-repo1.php-maven.org</id>
			<name>PHP-Maven 2 Release Repository</name>
			<url>http://repos.php-maven.org/releases</url>
			<releases>
				<enabled>true</enabled>
			</releases>
		</pluginRepository>

		<pluginRepository>
			<id>snapshot-repo1.php-maven.org</id>
			<name>PHP-Maven 2 Snapshot Repository</name>
			<url>http://repos.php-maven.org/snapshots</url>
			<releases>
				<enabled>false</enabled>
			</releases>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>

	<repositories>
		<repository>
			<id>release-repo1.php-maven.org</id>
			<name>PHP-Maven 2 Release Repository</name>
			<url>http://repos.php-maven.org/releases</url>
			<releases>
				<enabled>true</enabled>
			</releases>
		</repository>
		<repository>
			<id>snapshot-repo1.php-maven.org</id>
			<name>PHP-Maven 2 Snapshot Repository</name>
			<url>http://repos.php-maven.org/snapshots</url>
			<releases>
				<enabled>false</enabled>
			</releases>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
	</repositories>
	</profile>
</profiles>

Mittlerweile betreiben immer mehr Unternehmen eigene Repository-Server für ihre Produkte. Dazu gehören unter anderem Google, Java .NET und Activity, um einige öffentliche Server zu nennen. Da das Projekt Maven for PHP vergleichsweise sehr jung ist, sind derzeit nur die bekanntesten PHP-Projekte, wie beispielsweise Zend und Symfony, in das Repository migriert. In absehbarer Zukunft darf jedoch durchaus erwartet werden, dass weitere PHP-Projekte das Repository bereichern werden. Bei besonders dringlichen Fällen kann es hier hilfreich sein, eine Anfrage über die Google Mailing List zu stellen. Natürlich ist auch jeder, der sich an PHP for Maven beteiligen möchte, eingeladen, sich im Rahmen seiner Möglichkeiten einzubringen.

PHP-CLI

Damit Maven sich voll entfalten kann, ist es notwendig, das Command Line Interface (CLI) für PHP in der Konsole zu aktivieren. Mit dem CLI ist es möglich, PHP-Skripts ohne Webbrowser direkt auf der Kommandozeile auszuführen.

Bild 5: Output des Prompts für erfolgreiches Einbinden des PHP-CLI

Diese Funktion wird beispielsweise benötigt, um die Source-Code-Dokumentation über den phpDocumentor aus Maven heraus anzustoßen. Sobald der Pfad zum Verzeichnis der php.exe in die PATH-Variable aufgenommen wurde, können PHP-Skripts über die Konsole ausgeführt werden. Wie diese Aufgabe für Windows-Systeme gelöst wird, wurde bereits in dem vorangegangenen Abschnitt über die Installation ausführlich beschrieben. Der Erfolg dieser Bemühung lässt sich durch die Anweisung php –v rasch überprüfen und wird im Erfolgsfall mit der Ausgabe der installierten PHP-Version quittiert. Auch wenn im ersten Blick die Installation umfangreich erscheint, sind nur wenige Schritte durchzuführen, um ein einsatzfähiges System zu erhalten. Der geringe Aufwand wird durch umfangreiche Funktionen zur Projektautomatisierung schnell entlohnt.

Ein Füllhorn an Möglichkeiten

Es steht dem Benutzer frei, für welches Szenario er Maven in einem Projekt einsetzen möchte. Hier ein Liste möglicher Einsatzszenarien:

Die erste Position dieser Liste führt erwartungsgemäß das Dependency Management an. Über den Mechanismus können Artefakte fremder Hersteller ebenso dem eigenen Projekt hinzugefügt werden wie selbst entwickelte Bibliotheken.

Neben diesem Aspekt ist ein weiteres wichtiges Thema der Softwaretest. Maven erlaubt es, verschiedenste Test-Frameworks im Build-Lifecycle zu integrieren. Der bekannteste Vertreter unter den Unit-Tests, phpUnit, ist bereits im Public-Repository von Maven for PHP enthalten.

Wie bereits angedeutet, kommt die Generierung der API-Dokumentation mit dem phpDocumentator ebenfalls nicht zu kurz.

Aber auch ein Blick zu den klassischen Maven-Plug-ins ist in einigen Fällen lohnenswert. So besteht die Möglichkeit, aus Maven heraus Ant-Aufrufe zu starten und abzuarbeiten, was die Funktionsvielfalt um einiges erweitert.

Ein beliebtes Thema für Webseiten sind script- und CSS-Minimierer. Code-Beautifier oder Obsfukatoren stellen weitere Punkte auf der Liste dar. Auch Code-Analyzer-Werkzeuge wie Checkstyle können eingebunden werden und bieten damit der Projektleitung einen guten Einblick in die Softwarequalität.

Eine weitere Möglichkeit besteht darin, ganze Internetseiten zu generieren. So ist beispielsweise die Homepage des Projekts aus Maven heraus erzeugt worden.

Das Charmante an all diesen Möglichkeiten ist die Tatsache, dass für die Funktionalität keine weitere Software installiert werden muss. Alle Funktionen sind durch Maven-Plug-ins umgesetzt und werden bei Bedarf über das Dependency Management nachgeladen. Sollte dennoch Wünsche offen bleiben, ist es jederzeit möglich, über das Plug-in-API eigene Erweiterungen zu schreiben.

Für Unternehmen bietet Maven einen weiteren Vorteil. Der Einsatz dieses Werkzeugs unterstützt bei gutem Moduldesign die Wiederverwendung von Softwarekomponenten. Diese Tatsache kann den entscheidenden Vorsprung gegenüber der Konkurrenz bedeuten, da Projekte schneller abgewickelt werden können.


So wird Unternehmenswissen greifbar

Das Fachwissen der eigenen Mitarbeiter ist für jede Organisation ein bedeutender Wirtschaftsfaktor. Umso wichtiger ist es, die Erfahrungen und Fachkenntnisse dauerhaft zu speichern und anderen Mitarbeitern zur Verfügung zu stellen. Ein zentraler Knowledge-Management-Server übernimmt diese Aufgabe und hilft, langfristig die Produktivität im Unternehmen zu sichern.

(c) 2011 Marco Schulz, Materna Monitor, Ausgabe 2, S.32-33

Die Komplexität der heutigen stark vernetzten Arbeitswelt erfordert ein reibungsloses Zusammenspiel unterschiedlichster Spezialisten. Eine wichtige Rolle spielt hierbei der Wissenstransfer. Erschwert wird dieser Austausch, wenn die Teammitglieder an unterschiedlichen Standorten mit verschiedenen Zeitzonen arbeiten oder aus anderen Kulturkreisen kommen. Unternehmen mit weltweiten Standorten kennen diese Problematik und haben entsprechende Strategien für ein unternehmensweites Wissens-Management entwickelt. Um dieses erfolgreich einzuführen, sollte die einzusetzende IT-Lösung als Methodik aufgefasst werden anstatt das eigentliche Werkzeug in den Vordergrund zu stellen. Haben die Verantwortlichen die Entscheidung für eine bestimmte Software-Lösung getroffen, sollte diese auch konsequent beibehalten werden. Ein häufiger Systemwechsel mindert die Qualität der Verknüpfungen zwischen den gespeicherten Inhalten. Da es keinen normierten Standard für die Repräsentation von Wissen gibt, können bei einem Wechsel auf neue Software-Lösungen erhebliche Konvertierungsverluste eintreten.

Verschiedene Mechanismen für unterschiedliche Inhalte

Informationen lassen sich in IT-Systemen auf verschiedene Weise speichern. Die einzelnen Repräsentationsformen unterscheiden sich durch die Darstellung, Strukturierung und Verwendung. Um Dokumente gemeinsam konfliktfrei bearbeiten und gleichzeitig versionieren zu können, wie es bei Spezifikationen oder Dokumentationen notwendig ist, eignen sich Wikis [1] optimal, da sie genau für diesen Einsatz ursprünglich entwickelt wurden. Die dort gespeicherten Dokumente sind üblicherweise projektspezifisch und sollten auch so organisiert werden.

Projektübergreifende Dokumente im Wiki sind zum Beispiel Fachworterklärungen, ein zentrales Abkürzungsverzeichnis oder ein Who is Who der Unternehmensmitarbeiter inklusive Kontaktdaten und Themengebieten. Letztere lassen sich wiederum mit der Fachworterklärung verknüpfen. Übergreifende Inhalte können dann zentral aktuell gehalten werden und lassen sich komfortabel in die entsprechenden Projektdokumente verlinken. Dieses Vorgehen vermeidet unnötige Wiederholungen und die zu lesenden Dokumente werden kürzer, enthalten aber dennoch alle notwendigen Informationen. Johannes Siedersleben hat bereits 2003 in seinem Buch Softwaretechnik [2] die Risiken zu langer Dokumentationen beschrieben.

Wissen, das eher den Charakter einer FAQ aufweist, sollte besser über ein Forum organisiert werden. Die Gruppierung nach Themen, in denen Fragen nach dem Muster „Wie kann ich …?“ hinterlegt sind, erleichtern das Auffinden möglicher Lösungen. Besonders attraktiv ist die Tatsache, dass ein solches Forum sich mit der Zeit dem Bedarf nach weiterentwickelt. Denn Nutzer haben die Möglichkeit, eigene Fragen zu formulieren und in das Forum einzustellen. In aller Regel lassen qualifizierte Antworten auf neu gestellte Fragen nicht lange auf sich warten.

Geeignete Kandidaten für Blogs sind zum Beispiel allgemeine Informationen zum Unternehmen, Statusberichte oder Tutorials. Dies sind Dokumente, die eher einen informativen Charakter haben, nicht formgebunden sind oder sich schwer einem speziellen Thema zuordnen lassen. Kurzinformationen (Tweets [3]) über Twitter, die in Kanälen thematisch zusammengefasst sind, können die Projektarbeit ebenfalls bereichern. Sie minimieren zusätzlich die E-Mails im eigenen Postkasten. Beispiele dafür sind Reminder zu einem bestimmten Event, ein Newsflash zu neuen Produktversionen oder eine Information über einen erfolgreich abgeschlossenen Arbeitsprozess. Tweets in die Projektarbeit zu integrieren, ist relativ neu und entsprechend rar sind hierfür geeignete Software-Lösungen.

Natürlich ist die Aufzählung von Möglichkeiten an dieser Stelle bei weitem noch nicht erschöpft. Die Beispiele vermitteln aber bereits einen guten Überblick, wie Unternehmen ihr Wissen organisieren können. Mit der Verknüpfung der einzelnen Systeme zu einem Portal [4], das eine übergreifende Suche und Benutzerverwaltung hat, entsteht so schnell ein Netzwerk, das sich auch als Cloud-Lösung eignet.

Für die Akzeptanz einer Wissensplattform ist die Anwenderfreundlichkeit ein entscheidender Faktor. Lange Einarbeitungszeiten, unübersichtliche Strukturierungen und eine umständliche Bedienung können schnell zur Ablehnung führen. Mit einer Zugangsberechtigung zu den einzelnen Inhalten auf Gruppenebene wird auch der Sicherheit genüge getan. Ein gutes Beispiel dafür ist das Enterprise Wiki Confluence [5]. Es ermöglicht, den einzelnen Dokument-Ebenen verschiedene Lese- und Schreib-Berechtigungen zuzuordnen.

Naturgemäß kann man von einem Entwickler nicht erwarten, dass er nach erfolgreicher Implementierung sein Werk mit den richtigen Worten für die Nachwelt verständlich beschreibt. Dass die Qualität der Texte in vielen Dokumentationen nicht immer ausreichend ist, hat auch die Hochschule Merseburg erkannt und bietet den Studiengang Technische Redaktion [6] an. Als geeignetes Mittel zur Qualitätssicherung der Inhalte hat sich daher das Querlesen durch andere Projektmitglieder erwiesen. Um das Verfassen von Texten zu erleichtern, ist es hilfreich, einen kleinen Leitfaden – ähnlich der Coding Convention – bereitzustellen.

Fazit

Eine Wissensdatenbank lässt sich nicht von heute auf morgen umsetzen. Es braucht Zeit, bis darin genügend Informationen zusammengetragen sind. Erst durch Interaktion und Korrekturen von Unverständlichkeiten erreicht das Wissen eine Qualität, die zum Transfer einlädt. Jeder Mitarbeiter sollte dazu ermutigt werden, vorhandene Texte mit neuen Erkenntnissen anzureichern, unverständliche Passagen aufzulösen oder Suchbegriffe zu ergänzen. Wenn der Prozess der Wissensschöpfung und Verteilung in dieser Form gelebt wird, werden weniger Dokumente verwaisen und die Informationen sind stets aktuell.

Ressourcen

Abonnement / Subscription

[English] This content is only available to subscribers.

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