Clean Coder

Verhaltensregeln für professionelle Programmierer

Robert C. Martin

Übersetzung aus dem Amerikanischen von Jürgen Dubau

»Mit seinem aktuellen Buch legt ‚Uncle Bob’ Martin die Latte definitiv sehr hoch. Darin erläutert er, was er von einem professionellen Programmierer hinsichtlich der Verwaltung von Interaktionen, Zeitmanagement, Arbeiten unter Druck, Teamwork und der Wahl der eingesetzten Tools erwartet. Über TDD und ATDD hinaus erklärt Martin, was jeder Programmierer, der sich als Profi versteht, nicht nur wissen, sondern auch befolgen muss, um das junge Arbeitsfeld der Software-Entwicklung auszubauen.«

– Markus Gärtner
Senior Software Developer, it-agile GmbH
www.it-agile.de, www.shino.de

»Manche technischen Bücher inspirieren und informieren, manche erfreuen und unterhalten einen. Selten schafft aber ein technisches Buch all dies auf einmal. Die Bücher von Robert Martin haben das bei mir immer geschafft, und Clean Coder bildet dabei keine Ausnahme. Lesen Sie die Lektionen in diesem Buch, lernen und leben Sie sie, dann dürfen Sie sich mit Fug und Recht als Software-Profi bezeichnen.«

– George Bullock
Senior Program Manager, Microsoft Corp.

»Wird man nach dem Informatikstudium noch auf weitere Pflichtlektüre hingewiesen, dann müsste dieses Buch dazugehören. In der realen Welt verschwindet der eigene schlechte Code nicht, wenn das Semester vorüber ist, man bekommt keine 1 für einen Marathon-Programmiereinsatz in der Nacht vor dem Abgabetermin, und am schlimmsten: Man muss mit anderen Leuten klarkommen. So sind Coding-Gurus nicht notwendigerweise auch Profis. Clean Coder beschreibt die Reise zum Professionalismus ... und schafft das auf eine bemerkenswert unterhaltsame Weise.«

– Jeff Overbey
University of Illinois at Urbana-Champaign

»Clean Coder ist weitaus mehr als nur eine Sammlung von Regeln oder Richtlinien. Darin enthalten ist hart erarbeitete Weisheit und ein Wissen, das man normalerweise durch viele Jahre von Versuch und Irrtum erlangt, während man bei einem Meister seines Faches in die Lehre geht. Wenn Sie sich als Software-Profi bezeichnen, dann brauchen Sie dieses Buch.«

– R. L. Bogetti
Lead System Designer, Baxter Healthcare
www.RLBogetti.com

Impressum

Bibliografische Information der Deutschen Nationalbibliothek

Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über <http://dnb.d-nb.de> abrufbar.

ISBN 978-3-8266-3208-2

1. Auflage 2014

www.mitp.de

E-Mail: kundenservice@hjr-verlag.de

Telefon: +49 6221 / 489 -555

Telefax: +49 6221 / 489 -410

© 2014 mitp, eine Marke der Verlagsgruppe Hüthig Jehle Rehm GmbH Heidelberg, München, Landsberg, Frechen, Hamburg

Dieses Werk, einschließlich aller seiner Teile, ist urheberrechtlich geschützt. Jede Verwertung außerhalb der engen Grenzen des Urheberrechtsgesetzes ist ohne Zustimmung des Verlages unzulässig und strafbar. Dies gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und die Einspeicherung und Verarbeitung in elektronischen Systemen.

Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Warenbezeichnungen usw. in diesem Werk berechtigt auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im Sinne der Warenzeichen- und Markenschutz-Gesetzgebung als frei zu betrachten wären und daher von jedermann benutzt werden dürften.

Authorized translation from the English language edition, entitled CLEAN CODER, THE: A CODE OF CONDUCT FOR PROFESSIONAL PROGRAMMERS, 1st Edition, 0137081073 by MARTIN, ROBERT C., published by Pearson Education, Inc, publishing as Prentice Hall, Copyright © 2011 by Pearson Education, Inc.

All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Pearson Education, Inc. GERMAN language edition published by mitp, an imprint of Verlagsgruppe Hüthig Jehle Rehm GmbH, Copyright © 2014.

Lektorat: Sabine Schulz

Fachkorrektorat: Claudia Nölker

Korrektorat: Sandra Gottmann

electronic publication: III-satz, Husby, www.drei-satz.de

Dieses Ebook verwendet das ePub-Format und ist optimiert für die Nutzung mit dem iBooks-reader auf dem iPad von Apple. Bei der Verwendung anderer Reader kann es zu Darstellungsproblemen kommen.

Der Verlag räumt Ihnen mit dem Kauf des ebooks das Recht ein, die Inhalte im Rahmen des geltenden Urheberrechts zu nutzen. Dieses Werk, einschließlich aller seiner Teile, ist urheberrechtlich geschützt. Jede Verwertung außerhalb der engen Grenzen des Urheherrechtsgesetzes ist ohne Zustimmung des Verlages unzulässig und strafbar. Dies gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und Einspeicherung und Verarbeitung in elektronischen Systemen.

Der Verlag schützt seine ebooks vor Missbrauch des Urheberrechts durch ein digitales Rechtemanagement. Bei Kauf im Webshop des Verlages werden die ebooks mit einem nicht sichtbaren digitalen Wasserzeichen individuell pro Nutzer signiert.

Bei Kauf in anderen ebook-Webshops erfolgt die Signatur durch die Shopbetreiber. Angaben zu diesem DRM finden Sie auf den Seiten der jeweiligen Anbieter.

Anhang A: Werkzeuge und Hilfsmittel

1978 arbeitete ich bei Teradyne an dem bereits beschriebenen Telefontestsystem. Das System umfasste etwa 80.000 Zeilen in M365 Assembler geschriebenen Quellcode, und den speicherten wir auf Magnetbändern.

Die Bänder ähnelten jenen 8-Spur-Stereo-Bandkassetten, die damals in den 1970ern so beliebt waren. Dieses Endlosband wurde vom Bandlaufwerk nur in eine Richtung bewegt. Die Kassetten gab es in 10, 25, 50 und 100 Zoll Länge. Je länger das Band war, desto länger dauerte auch das »Zurückspulen«, weil das Laufwerk einfach solange nach vorne spulte, bis der »Ladepunkt« gefunden war. Ein 100-Zoll-Band brauchte fünf Minuten, um zum Ladepunkt zu kommen. Also passten wir bei der Wahl der Länge unserer Bänder gut auf [1].

Logischerweise wurden die Bänder in Dateien unterteilt, und man konnte so viele Dateien auf einem Band haben, wie draufpassten. Um eine Datei zu finden, lud man das Band und sprang dann von einer Datei zur nächsten, bis die gewünschte gefunden war. Wir führten auf einer Liste an der Wand das Verzeichnis für den Quellcode, damit wir immer wussten, wie viele Dateien jeweils zu überspringen waren.

Auf einem Regal im Labor lag eine Kopie des Master-Bands des 100-Zoll-Quellcodebands. Darauf stand Master. Wenn wir eine Datei bearbeiten wollten, wurde das Master-Quellcodeband in das eine Laufwerk geladen und ein leeres 10-Zoll-Band ins andere. Wir sprangen durch den Master bis zur benötigten Datei, die dann auf das leere Band kopiert wurde. Beide Bänder wurden »zurückgespult« und der Master wieder ins Regal gestellt.

Im Labor hing an einem Schwarzen Brett eine spezielle Liste der Verzeichnisse auf dem Master. Nachdem wir die zu bearbeitenden Dateien kopiert hatten, steckten wir eine farbige Nadel neben den Namen dieser Datei ins Brett. So wurden Dateien ausgecheckt!

Wir bearbeiteten die Bänder auf einem Bildschirm. Unser Texteditor ED-402 war tatsächlich sehr gut. Er war ziemlich ähnlich wie vi. Wir lasen eine »Seite« vom Band, bearbeiteten die Inhalte und schrieben diese Seite dann zurück, um die nächste zu lesen. Eine Seite bestand normalerweise aus 50 Codezeilen. Man konnte auf dem Band nicht »vorblättern«, welche Seiten kommen, und auch nicht zurück, um die bisher bearbeiteten Seiten zu sehen. Also arbeiteten wir mit Listings.

In der Tat markierten wir unsere Listings mit allen anstehenden Änderungen, und dann erst bearbeiteten wir die Dateien unseren Auszeichnungen gemäß. Niemand schrieb oder modifizierte Code am Terminal! Das galt als Selbstmord.

Wenn wir mit den Änderungen bei allen zu bearbeitenden Dateien fertig waren, fügten wir diese Dateien auf den Master ein, um ein funktionierendes Band zu erstellen. Mit diesem Band haben wir dann unsere Kompilierungen und Tests durchgeführt.

Nachdem alle Tests abgeschlossen und wir sicher waren, dass unsere Änderungen funktionierten, schauten wir aufs Schwarze Brett. Wenn keine neuen Nadeln im Brett steckten, etikettierten wir das funktionierende Band einfach zu Master um und zogen alle Nadeln aus dem Brett. Falls es neue Nadeln gab, zogen wir unsere heraus und übergaben das funktionierende Band an die Person, deren Nadeln immer noch im Brett steckten. Dann musste der sich um die Zusammenführung kümmern.

Weil wir zu dritt waren und jeder seine eigene Farbe hatte, wussten wir gleich, wer welche Dateien ausgecheckt hatte. Und weil wir alle im gleichen Labor arbeiteten und ständig im Gespräch waren, hatten wir den Status des Bretts im Kopf. Also war das Brett meist überflüssig, und oft brauchten wir es gar nicht.

A.1  Tools​

Heutzutage steht den Software-Entwicklern eine große Bandbreite von Tools zur Verfügung. Mit den meisten muss man sich nicht näher beschäftigen, aber es gibt ein paar, mit denen jeder Software-Entwickler vertraut sein sollte. In diesem Kapitel beschreibe ich meinen aktuellen persönlichen Werkzeugkasten. Ich habe keine umfassende Untersuchung aller verfügbaren Tools gemacht, also ist dies nicht als erschöpfende Übersicht zu betrachten. Hier stellte ich einfach die Sachen vor, mit denen ich arbeite.

A.2  Quellcodekontrolle​

Wenn es um die Quellcodekontrolle geht, sind Open Source-Tools meist die beste Option. Warum? Weil sie von Entwicklern für Entwickler geschrieben wurden. Diese Tools schreiben sich die Entwickler selbst, wenn sie etwas brauchen, was funktioniert.

Es gibt auch eine ganze Reihe teurer, kommerzieller »Enterprise«-Versionen solcher Kontrollsysteme. Ich habe gemerkt, dass diese weniger an Entwickler als an Manager, Geschäftsführer und »Tool-Groups« verkauft werden. Ihre Feature-Liste ist beeindruckend und überzeugend. Leider haben sie oft nicht jene Features, die Entwickler eigentlich brauchen. Das wichtigste davon ist Tempo.

A.2.1  Ein »Enterprise«-System der Quellcodekontrolle

Vielleicht hat Ihre Firma ein kleines Vermögen in ein solches »Enterprise«-System investiert. Falls ja, haben Sie mein Beileid. Sie sollten aus diplomatischen Gründen wahrscheinlich lieber nicht herumlaufen und allen erzählen: »Uncle Bob sagt, damit solle man nicht arbeiten.« Doch es gibt eine einfache Lösung.

Sie können Ihren Quellcode am Ende jeder Iteration ins »Enterprise«-System einchecken (etwa alle 14 Tage) und in der Mitte jeder Iteration dann mit einem der Open Source-Systeme arbeiten. So sind alle glücklich und zufrieden, es werden keine Firmenregeln verletzt, und Ihre Produktivität bleibt konstant hoch.

A.2.2  Pessimistisches​ kontra optimistisches Locking​

In den 1980ern schien pessimistisches Locking eine prima Idee zu sein. Schließlich ist der einfachste Weg, um die Aktualisierungsprobleme beim gleichzeitigen Zugriff zu verwalten, sie zu serialisieren. Wenn ich eine Datei bearbeite, lassen Sie also besser die Finger davon. Tatsächlich war das von mir eingesetzte System der farbigen Nadeln Ende der 1970er eine Form des pessimistischen Lockings. Wenn eine Nadel neben der Datei steckte, dann lassen alle anderen sie in Ruhe.

Natürlich bringt auch pessimistisches Locking Probleme. Wenn ich eine Datei sperre und in Urlaub gehe, sitzen alle auf dem Trocknen, die diese Datei bearbeiten wollen. Auch wenn ich eine Datei nur ein oder zwei Tage sperre, sorge ich unter Umständen bei anderen für Verzögerungen, die an der gleichen Datei etwas ändern müssen.

Unsere Tools sind beim Zusammenführen von gleichzeitig bearbeiteten Quellcodedateien weitaus besser geworden. Eigentlich ist das wirklich erstaunlich, wenn man sich das mal genau überlegt: Die Tools nehmen sich beide Dateien und deren Vorgänger vor und finden anhand mehrerer Strategien heraus, wie man diese gleichzeitigen Änderungen integriert. Und dabei erledigen sie ihre Aufgabe sehr gut.

Also ist die Ära des pessimistischen Lockings vorüber. Wir müssen Dateien nicht mehr sperren, wenn wir sie auschecken. Tatsächlich brauchen wir nicht einmal mehr einzelne Dateien auszuchecken, sondern gleich das ganze System und bearbeiten alle erforderlichen Dateien.

Wenn dann unsere Änderungen eingecheckt werden sollen, führen wir eine »Update«-Operation durch. So wissen wir, ob jemand vor uns Code eingecheckt hat. Diese Operation führt automatisch die meisten Änderungen zusammen, findet Konflikte und hilft, den Rest einzufügen. Dann committen wir den zusammengeführten Code.

Ich werde mich weiter hinten im Kapitel noch ausführlich über die Rolle verbreiten, die automatisierte Tests und die fortlaufende Integration bei diesem Prozess spielen. Hier soll nur erwähnt werden, dass niemals Code eingecheckt wird, der nicht alle Tests bestanden hat. Absolut nie!

A.2.3  CVS​/SVN​

Damals war CVS das bewährte einsatzbereite Quellcodekontrollsystem. Es war zu damaligen Zeiten gut, ist aber für heutige Projekte nun etwas in die Jahre gekommen. Obwohl es sehr gut mit einzelnen Dateien und Verzeichnissen umgehen kann, kann es nicht gut Dateien umbenennen und Verzeichnisse löschen. Und der Attic ... Tja, je weniger man darüber sagt, desto besser.

Subversion hingegen funktioniert wirklich sehr schön. Damit kann man das gesamte System in einem Durchgang auschecken. Updaten, Mergen und Committen gehen ganz leicht. Solange Sie keine Verzweigungen brauchen, kann man mit SVN-Systemen ziemlich einfach umgehen.

Verzweigungen​​

Bis 2008 versuchte ich, Verzweigungen (Branches​) generell zu meiden, und ließ nur einfachste Formen zu. Wenn ein Entwickler einen Branch erstellte, musste dieser Zweig vor Ende der Iteration wieder in den Hauptstrang zurückgeführt werden. Tatsächlich war ich beim Thema Verzweigung so streng, dass es in den Projekten, mit denen ich zu tun hatte, nur höchst selten zum Einsatz kam.

Wenn Sie SVN nehmen, dann halte ich dies immer noch für eine gute Richtlinie. Allerdings sind ein paar neue Tools erschienen, durch die die Karten komplett neu gemischt werden. Es handelt sich um verteilte Quellcodekontrollsysteme, und git ist mein Favorit.

A.2.4  git

Ich arbeite seit Ende 2008 mit git​, und es hat komplett die Art und Weise verändert, wie ich mit Quellcodekontrolle umgehe. Es sprengt den Rahmen dieses Buches zu beschreiben, warum dieses Tool alles aufgemischt hat. Aber wenn man Abbildung A.1 mit Abbildung A.2 vergleicht, könnte man dazu eine Menge ausführlich erklären, was ich aber hier nicht machen werde.

Abbildung A.1 zeigt das Ergebnis von einigen Wochen Arbeit am FitNesse-Projekt unter Verwendung von SVN. Sie sehen die Auswirkungen meiner strengen Regel, die Verzweigungen zu vermeiden. Wir bauten einfach keine Verzweigungen ein. Stattdessen arbeiteten wir mit häufigen Updates, Zusammenführungen und Commits für den Hauptstrang.

Abb. A.1: FitNesse unter Subversion

Abbildung A.2 zeigt ein paar Wochen Entwicklungsarbeit am gleichen Projekt unter git. Leicht erkennen Sie, wie wir an den verschiedenen Stellen verzweigen und wieder zusammenführen. Nun habe ich aber nicht die Zügel bei meiner Keine-Verzweigungen-Politik fahren lassen, sondern es war einfach ganz naheliegend und völlig praktisch, so zu arbeiten. Jeder Entwickler kann individuell sehr kurzlebige Branches erstellen und sie dann auf Wunsch auch wieder zusammenführen.

Abb. A.2: FitNesse unter git

Beachten Sie, dass kein Hauptstrang erkennbar ist. Das liegt daran, dass es keinen gibt. Bei git braucht man so etwas wie ein zentrales Repository oder einen Hauptstrang nicht. Jeder Entwickler führt seine eigene Kopie der gesamten Projekt-History auf seinem lokalen Rechner. Er checkt aus dieser lokalen Kopie aus und wieder ein und führt seinen Code mit anderen bei Bedarf zusammen.

Es stimmt, dass ich ein spezielles goldenes Repository führe, in das ich alle Releases und zwischenzeitigen Builds verschiebe. Aber dieses Repository als Hauptstrang zu bezeichnen, wäre etwas daneben. Es ist wirklich nur ein praktischer Snapshot der gesamten History, die jeder Entwickler bei sich lokal führt.

Wenn Sie das nicht begreifen, ist es nicht schlimm. git ist anfangs schon recht knifflig. Man muss sich bei dessen Arbeitsweise eingewöhnen. Aber ich will Ihnen was sagen: In git und anderen ähnlichen Tools sehen wir die Zukunft der Quellcodekontrolle.

A.3  IDE/Editor​

Als Entwickler verbringen wir die meiste Zeit damit, Code zu lesen und zu bearbeiten. Im Laufe der Jahrzehnte haben sich die dabei eingesetzten Tools grundlegend gewandelt. Manche sind immens leistungsfähig, und andere haben sich seit den 1970ern nur wenig verändert.

A.3.1  vi​

Man könnte annehmen, die Tage von vi als primärem Entwicklungseditor seien lange vorüber. Heutzutage gibt es Tools, die vi (und andere, einfache Texteditoren) um Längen deklassieren. Aber in Wahrheit findet vi jetzt wieder sehr viel Anklang, weil es so einfach zu verwenden, schnell und flexibel ist. vi ist vielleicht nicht so leistungsfähig wie Emacs oder Eclipse, aber immer noch ein schneller und leistungsfähiger Editor.

Aber nun muss ich doch gestehen, dass ich bei vi kein Power-User mehr bin. Es gab mal Zeiten, da war ich als »vi-Gott« bekannt – das ist lange vorbei. Gelegentlich hole ich vi mal hervor, wenn ich schnell eine Textdatei bearbeiten will. Ich habe es sogar kürzlich noch benutzt, um schnell an einer Java-Quellcodedatei in einer entfernten Umgebung etwas zu ändern. Aber wirklich mit vi programmiert habe ich in den vergangenen zehn Jahren kaum.

A.3.2  Emacs​

Emacs ist immer noch einer der leistungsfähigsten Editoren überhaupt und wird das wahrscheinlich auch in den nächsten Dekaden sein – das interne Lisp-Modell garantiert das. Emacs ist ein vielseitiges Allzweck-Tool, dem nichts das Wasser reichen kann. Andererseits finde ich, dass Emacs nicht wirklich mit den spezialisierten IDEs mithalten kann, die jetzt den Markt beherrschen. Und Code zu bearbeiten, ist eben kein Allzweck -Job.

In den 1990ern war ich Emacs-Fanatiker. Ich zog anderes nicht einmal in Betracht. Die damaligen Point-and-Click-Editoren waren ein lachhaftes Spielzeug, das kein Entwickler wirklich ernst nehmen konnte. Doch Anfang des Jahres 2000 lernte ich IntelliJ kennen, meine aktuelle IDE der Wahl, und habe nie mehr zurückgeschaut.

A.3.3  Eclipse​/IntelliJ​

Ich bin absolut überzeugter IntelliJ-User und liebe es. Ich schreibe damit Java, Ruby, Clojure, Scala, JavaScript und vieles andere. Dieses Tool wurde von Programmierern erstellt, die begreifen, was Programmierer brauchen, wenn sie Code schreiben. Im Laufe der Jahre hat es mich selten enttäuscht und fast immer erfreut.

Eclipse gleicht in Leistung und Umfang IntelliJ. Die beiden sind einfach um Längen besser als Emacs, wenn’s ums Bearbeiten von Java-Code geht. Es gibt andere IDEs in dieser Kategorie, aber ich stelle sie hier nicht vor, weil ich keine direkte Erfahrung mit ihnen habe.

Diese IDEs hängen Tools wie Emacs ab, weil sie so extrem leistungsfähige Features zur Manipulation von Code enthalten. Bei IntelliJ können Sie beispielsweise mit einem einzigen Befehl aus einer Klasse eine Superklasse extrahieren. Neben vielen weiteren hervorragenden Features können Sie Variablen umbenennen, Methoden extrahieren und Vererbung in Komposition konvertieren.

Mit diesen Tools geht es bei der Bearbeitung von Code nicht mehr länger um Zeilen und Zeichen, sondern um komplexe Manipulationen. Anstatt über die nächsten paar einzutippenden Zeichen und Zeilen nachzudenken, denken Sie an die bevorstehenden Transformationen. Kurz gesagt: Das Programmiermodell ist bemerkenswert anders und höchst produktiv.

Natürlich gibt es diese Leistungsfähigkeit nicht umsonst: Die Lernkurve ist steil, und die Einrichtungszeit für Projekte ist nicht unwesentlich. Diese Tools sind nicht leichtgewichtig, sondern brauchen im Betrieb viele Rechnerressourcen.

A.3.4  TextMate​

TextMate ist leistungsfähig und leichtgewichtig. Es vollbringt keine solch wundervollen Manipulationen wie IntelliJ und Eclipse und hat auch nicht die leistungsfähige Lisp-Engine und Library wie Emacs. Es ist nicht so flott und flüssig wie vi. Doch die Lernkurve ist flach und die Bedienung intuitiv.

Ich arbeite hier und da mal mit TextMate, vor allem gelegentlich bei C++. Ich würde Emacs für ein großes C++-Projekt nehmen, aber ich bin etwas aus der Übung, um für die kurzen, kleinen C++-Aufgaben Emacs einzusetzen.

A.4  Issue-Tracking-System​e

Momentan arbeite ich mit Pivotal Tracker. Im Einsatz ist es ein elegantes und einfaches System, dass sehr schön zum agilen/iterativen Ansatz passt. Darüber können alle Stakeholder und Entwickler schnell miteinander kommunizieren. Ich bin sehr damit zufrieden.

Bei sehr kleinen Projekten habe ich manchmal Lighthouse genommen, da es sehr schnell und einfach einzurichten und verwendbar ist. Aber es reicht kaum an den Leistungsumfang von Tracker heran.

Ich habe auch oft einfach ein Wiki genommen. Wikis sind für interne Projekte ganz prima. Damit kann man jedes beliebige Schema einrichten. Man wird nicht zu einem bestimmten Prozess oder in eine rigide Struktur gezwungen. Man kann sie schnell und einfach verstehen und nutzen.

Manchmal ist das allerbeste Issue-Tracking-System ein Schwarzes Brett und eine Handvoll Karten. Das Schwarze Brett wird in Spalten wie »To Do«, »In Bearbeitung« und »Erledigt« aufgeteilt. Die Entwickler verschieben die Karten einfach entsprechend in die jeweilige Spalte. Tatsächlich ist dies heutzutage vielleicht das am häufigsten von agilen Teams eingesetzte Issue-Tracking-System.

Meinen Kunden empfehle ich, zuerst mit einem manuellen System wie dem Schwarzen Brett anzufangen, bevor sie sich ein Tracking-Tool zulegen. Wenn man das manuelle System gemeistert hat, weiß man genug, um sich ein passendes Tool auszuwählen. Und tatsächlich könnte die passende Wahl auch lauten, manuell weiterzumachen.

A.4.1  Bug-Zähler​

Entwicklerteams brauchen definitiv eine Auflistung aller anstehenden Aufgaben. Dazu gehören sowohl neue Tasks und Features als auch zu behebende Bugs. Für jedes Team in vernünftiger Größe (fünf bis zwölf Entwickler) sollte diese Liste Dutzende bis Hunderte von Einträgen umfassen. Keine dreistelligen Einträge!

Wenn Sie Tausende von Bugs haben oder auch Tausende von Features und/oder Tasks, läuft irgendetwas schief. Generell sollte die Liste der zu klärenden Themen relativ klein und von daher mit einem leichtgewichtigen Tool wie Lighthouse, Tracker oder einem Wiki zu verwalten sein.

Dafür sind auch kommerzielle Tools erhältlich, die recht anständig zu sein scheinen. Ich habe Kunden erlebt, die damit arbeiten, aber selbst hatte ich noch keine Gelegenheit dazu. Ich stehe diesen Tools nicht ablehnend gegenüber, solange die Zahl der Fälle klein und verwaltbar bleibt. Wenn mit solchen Tools Tausende von Fällen nachverfolgt werden müssen, dann verliert das Wort »Nachverfolgung« seinen Sinn. Sie werden zu Müllhalden voller Aufgaben (und stinken oft auch genauso).

A.5  Continuous Build​

Kürzlich habe ich für Continuous Builds mit Jenkins​ als Engine gearbeitet. Dieses leichtgewichtige, einfache Tool benötigt praktisch keine Einarbeitungszeit. Man lädt es herunter, startet es, nimmt ein paar schnelle, einfache Konfigurationen vor und kann sich gleich an die Arbeit machen. Sehr schön!

Meine Philosophie über Continuous Builds ist einfach: Man sollte sie ins Quellcodekontrollsystem einklinken. Sobald jemand Code eincheckt, sollte es automatisch einen Build vornehmen und den Status dann ans Team melden.

Das Team muss den Build einfach immer funktionsfähig halten. Wenn der Build misslingt, sollte dieser Vorfall bei allen dafür sorgen, dass sie den Griffel sofort fallenlassen und sich gleich treffen, um das Problem zu beheben. Der Fehler sollte keinesfalls einen Tag oder gar länger dauern dürfen.

Beim FitNesse-Projekt lasse ich jeden Entwickler das Skript für den Continuous Build durchlaufen, bevor er committen darf. Der Build dauert keine fünf Minuten und ist somit auch kein Hinderungsgrund. Falls hier Probleme auftauchen, werden sie von den Entwicklern ausgemerzt, bevor sie committen. Also ist der automatische Build selten problematisch. Wenn automatische Builds misslingen, hat sich als Hauptursache herausgestellt, dass irgendetwas mit der Umgebung problematisch ist, da meine Umgebung für automatische Builds sich deutlich von der Entwicklungsumgebung der Programmierer unterscheidet.

A.6  Tools für Unit-Test​s​

Jede Sprache hat ihr eigenes Tool für Unit-Tests. Meine Favoriten sind JUnit für Java, rspec für Ruby, NUnit für .NET, Midje für Clojure und CppUTest für C und C++.

Egal für welches Tool Sie sich entscheiden, ein paar grundlegende Features sollten alle unterstützen.

  1. Die Tests sollte man einfach und schnell ausführen können. Ob das über IDE-Plugins oder einfache Befehlszeilentools erfolgt, ist irrelevant, solange der Entwickler jederzeit nach Belieben diese Tests starten kann. Das Starten der Tests sollte ganz einfach und keine Hürde sein.

    Ich starte beispielsweise meine Tests mit CppUTest, indem ich in TextMate einfach command-M eintippe. Ich habe diesen Befehl so eingerichtet, dass er mein makefile startet. Das führt automatisch die Tests durch und gibt einen einzeiligen Bericht aus, wenn alle Tests bestanden wurden. IntelliJ unterstützt sowohl jUnit als auch rspec, also brauche ich nur auf einen Knopf zu drücken. Für nUnit bekomme ich mit dem Plugin Resharper den Test-Button.

  2. Das Tool sollte klar und deutlich das Bestehen oder Scheitern visualisieren. Dabei ist es gleichgültig, ob das ein grüner Balken oder eine Konsolennachricht mit den Worten »Alle Tests erfolgreich abgeschlossen« ist. Man muss nur schnell und eindeutig erkennen können, ob alle Tests bestanden wurden. Wenn man dazu einen mehrzeiligen Bericht oder schlimmer noch den Output zweier Dateien vergleichen muss, ist das Klassenziel verfehlt.

  3. Das Tool sollte klar und deutlich optisch den Fortschritt anzeigen. Dabei ist es nicht wichtig, ob das anhand eines Balkens oder einer Reihe Punkte erfolgt, solange man erkennt, dass der Vorgang noch andauert und die Tests weder abgewürgt noch abgebrochen wurden.

  4. Das Tool sollte einzelne Testfälle daran hindern, miteinander zu kommunizieren. jUnit erstellt dazu für jede Testmethode eine neue Instanz der Testklasse und unterbindet so, dass die Tests Instanzvariablen für die Kommunikation untereinander verwenden. Andere Tools durchlaufen die Testmethoden in zufälliger Reihenfolge, damit man sich nicht darauf verlassen kann, dass ein bestimmter Test einem anderen folgt. Das Tool sollte also egal mit welchem Mechanismus dafür sorgen, dass die Tests unabhängig voneinander bleiben. Voneinander abhängige Tests bilden eine sehr tiefe Falle, in die Sie keinesfalls tappen sollten.

  5. Mit dem Tool sollte man ganz einfach die Tests schreiben können. Bei jUnit wird das durch eine praktische API gewährleistet, mit der man Behauptungen aufstellen kann. Es arbeitet auch mit Reflektion und Java-Attributen, um die Testfunktionen von den normalen Funktionen zu unterscheiden. Damit kann eine gute IDE automatisch alle Ihre Tests identifizieren, was Ihnen die Mühe erspart, Suites zusammenzuschalten und fehleranfällige Testlisten zu erstellen.

A.7  Tools für Komponententest​s​

Mit diesen Tools werden Komponenten auf API-Ebene getestet. Damit soll gewährleistet sein, dass das Verhalten einer Komponente in einer Sprache beschrieben wird, die für Business und Qualitätssicherung verständlich ist. Tatsächlich wäre es ideal, wenn die Business-Analysten und die Qualitätssicherung diese Spezifikation mit diesem Tool selbst schreiben könnten.

A.7.1  Die »Definition of Done«

Mehr als mit jedem anderen Tool sind diese Komponententesttools der Weg, um die »Definition of Done« festzulegen. Wenn Business-Analysten und die Leute von der Qualitätssicherung gemeinsam eine Spezifikation erstellen, die das Verhalten einer Komponente definiert, und wenn diese Spezifikation dann als Test-Suite ausgeführt werden kann, die entweder bestanden wird oder misslingt, dann nimmt »done« eine sehr unzweideutige Bedeutung an: »Alle Tests wurden erfolgreich bestanden.«

A.7.2  FitNesse​

Mein Favorit bei den Tools für Komponententests ist FitNesse. Ich habe einen Großteil davon selbst geschrieben und bin der Hauptentwickler. Also ist es mein Baby.

Das System von FitNesse basiert auf Wikis, mit denen Business-Analysten und die Spezialisten für die Qualitätssicherung Tests in einem sehr einfachen tabellarischen Format schreiben. Diese Tabellen gleichen Parnas-Tabellen sowohl in der Form als auch dem Zweck. Damit kann man Tests schnell zu Suites zusammenstellen, und diese können dann jederzeit durchgeführt werden.

FitNesse ist in Java geschrieben, kann aber auch Systeme in allen möglichen Sprachen testen, weil es mit einem zugrundeliegenden Testsystem kommuniziert, das in einer beliebigen anderen Sprache geschrieben sein kann. Zu den unterstützten Sprachen gehören Java, C#/.NET, C, C++, Python, Ruby, PHP, Delphi und andere.

FitNesse baut auf den beiden Testsystemen Fit und Slim auf. Fit wurde von Ward Cunningham geschrieben und war die ursprüngliche Inspiration für FitNesse und seinesgleichen. Slim ist ein weitaus einfacheres und portableres Testsystem, das heutzutage von den FitNesse-Usern bevorzugt wird.

A.7.3  Andere Tools

Ich kenne mehrere andere Tools, die sich auch für Komponententests eignen.

  • RobotFX​ wurde von Nokia-Ingenieuren entwickelt. Dieses Tool arbeitet mit einem ähnlichen Tabellenformat wie FitNesse, basiert aber nicht auf Wikis, sondern arbeitet mit ganz einfachen Textdateien, die mit Excel o.Ä. vorbereitet wurden. Das Tool ist in Python geschrieben und kann über entsprechende Brücken auch Systeme in allen möglichen anderen Sprachen testen.

  • Green Pepper​ ist ein kommerzielles Tool, das FitNesse in mancherlei Hinsicht gleicht. Es basiert auf dem populären Confluence-Wiki.

  • Cucumber​ ist ein einfaches Text-Tool und wird von einer Ruby-Engine gesteuert, kann aber viele unterschiedliche Plattformen testen. Cucumber ist sprachlich im beliebten Gegeben/Wenn/Dann-Stil geschrieben.

  • JBehave​ ähnelt Cucumber und ist das logische Elternteil zu Cucumber. Geschrieben wurde es in Java.

A.8  Tool​s für Integrationstest​s

Tools für Komponententests sind auch für viele Integrationstests einsetzbar, passen aber weniger gut zu Tests, die über die UI getrieben werden.

Generell sollten Sie nicht viele Tests vom User Interface steuern lassen, weil UIs wegen ihrer Unbeständigkeit berüchtigt sind. Deswegen sind Tests sehr fragil, die das UI durchlaufen.

Doch gibt es ein paar Tests, die das UI durchlaufen müssen – am wichtigsten sind hier die Tests des UI selbst zu nennen Ein paar End-to-end-Tests sollten ebenfalls das gesamte, zusammengefügte System durchlaufen einschließlich des UI.

Am liebsten teste ich UIs mit Selenium und Watir.

A.9  UML​/MDA​

Anfang der 1990er Jahre war ich voller Hoffnung, dass die CASE-Tool-Industrie für eine radikale Änderung in der Art sorgen würde, wie Software-Entwickler arbeiten. Wenn ich aus diesen berauschenden Tagen auf die damalige Zukunft blickte, dachte ich, dass dann jeder in Diagrammen auf einem höheren Abstraktionsgrad programmieren würde und dass textlicher Code der Vergangenheit angehören würde.

Meine Güte, was lag ich da falsch! Mein Traum blieb nicht nur gänzlich unerfüllt, sondern jeder Versuch, sich in diese Richtung zu bewegen, wurde mit elendem Scheitern bestraft. Zwar sind Tools und Systeme im Umlauf, die das Potenzial demonstrieren, aber diese Tools setzen diesen Traum schlicht und einfach nicht um, und kaum jemand scheint Lust zu haben, damit zu arbeiten.

Die Software-Entwickler sollten die Details des textlichen Codes hinter sich lassen und Systeme auf der höheren Ebene einer Diagrammsprache erstellen. Tatsächlich gehört zu diesem Traum, dass sich Programmierer vielleicht gänzlich überflüssig machen. Architekten könnten aus UML-Diagrammen ganze Systeme schaffen. Riesige und coole Engines, die den Sorgen und Nöten einfacher Programmierer keine Beachtung schenken, würden diese Diagramme dann in ausführbaren Code umwandeln. Solcherart war der großartige Traum der Model Driven Architecture (MDA)​.

Bedauerlicherweise weist dieser prächtige Traum einen winzig kleinen Makel auf: Die MDA geht davon aus, dass Code das Problem ist. Aber Code ist nicht das Problem und ist es nie gewesen. Das Problem sind die Details.

A.9.1  Die Details​

Programmierer sind Verwalter der Details. Das ist unsere Aufgabe. Wir legen das Verhalten von Systemen bis in die kleinsten Kleinigkeiten fest. Dafür nehmen wir zufällig textliche Sprachen (Code), weil die bemerkenswert komfortabel sind (denken wir beispielsweise an Englisch).

Welche Art von Details managen wir?

Kennen Sie den Unterschied zwischen den Zeichen \n und \r? Das erste ist ein Zeilenvorschub und das zweite ein Wagenrücklauf. Welcher Wagen ist hier gemeint?

In den 1960er und Anfang der 1970er Jahre war die Teletype eines der häufig verwendeten Ausgabegeräte für Computer. Das Modell ASR33 [2] war am weitesten verbreitet.

Dieses Gerät enthielt einen Druckkopf, der zehn Zeichen pro Sekunde drucken konnte. Der Druckkopf bestand aus einem kleinen Zylinder, auf dem sich die erhabenen Zeichen befanden. Der Zylinder rotierte, hob und senkte sich, sodass sich vor dem Papier jeweils das richtige Zeichen befand, und dann schlug ein kleiner Hammer den Zylinder gegen das Papier. Zwischen Zylinder und Papier befand sich ein Farbband, und die Tinte darauf wurde in Form des Zeichens aufs Papier übertragen.

Der Druckkopf fuhr auf einem Wagen hin und her. Nach jedem Zeichen rückte der Wagen eine Stelle nach rechts und nahm den Druckkopf mit. Wenn der Wagen ans Ende der Zeile mit 72 Zeichen angekommen war, musste man den Wagen explizit zurückfahren lassen, indem man die Zeichen (\r = 0 x 0D) für den Wagenrücklauf sendete. Anderenfalls hätte der Druckkopf mit dem Drucken der Zeichen in der 72. Spalte weitergemacht und ein hässliches schwarzes Rechteck dort gemalt.

Natürlich reichte das noch nicht: Der Wagenrücklauf schob das Papier nicht bis in die nächste Zeile. Wenn man den Wagen zurückschickte aber kein Zeichen für den Zeilenvorschub (\n = 0 x 0A) sendete, wurde die neue Zeile über die alte gedruckt.

Somit lautete die Zeilenendsequenz für einen ASR33-Fernschreiber »\r\n«. Tatsächlich musste man dabei vorsichtig sein, weil der Wagen für den Rücklauf vielleicht länger als 100 ms brauchte. Wenn man »\n\r« sendete, wurde das nächste Zeichen vielleicht direkt beim Rücklauf gedruckt und produzierte dann ein verschmiertes Zeichen in der Zeilenmitte. Um auf Nummer sicher zu gehen, polsterten wir die Zeilenendsequenz oft mit ein oder zwei Ausradierzeichen[3] (0 x FF) aus.

Als in den 1970ern immer weniger Teletypes zum Einsatz kamen, verkürzten Betriebssysteme wie UNIX diese Sequenz einfach auf »\n«. Doch andere wie DOS arbeiteten weiterhin entsprechend der Konvention »\r\n«.

Wann haben Sie das letzte Mal mit Textdateien zu tun gehabt, die nach der »falschen« Konvention arbeiteten? Auf dieses Problem stoße ich mindestens einmal jährlich. Zwei identische Quellcodedateien sind nicht vergleichbar und generieren unterschiedliche Prüfsummen, weil sie verschiedene Zeilenenden verwenden. Bei Texteditoren funktioniert der Wortumbruch nicht korrekt oder sie fügen doppelte Leerzeichen in den Text ein, weil die Zeilenenden »verkehrt« sind. Programme stürzen ab, die nicht mit Leerzeichen umgehen können, weil sie »\r\n« als zwei Zeilen interpretieren. Manche Programme erkennen »\r\n«, aber »\n\r« nicht usw.

Das meine ich mit Details. Probieren Sie mal, in UML die grässliche Logik zu programmieren, um mit Zeilenenden umzugehen.

A.9.2  Keine Hoffnung, keine Änderung

Die Hoffnung der MDA-Bewegung bestand darin, dass ein Großteil dieser Details durch Verwendung von Diagrammen statt Code eliminiert werden kann. Diese Hoffnung hat sich bisher als aussichtslos erwiesen. Es stellt sich heraus, dass im Code gar nicht so viele zusätzliche Details eingebettet sind, die über Bilder eliminierbar wären. Bilder besitzen überdies ihre eigenen zufälligen Details. Sie weisen ihre eigene Grammatik, Syntax und Regeln sowie Einschränkungen auf. Also ist der Unterschied im Detail letzten Endes nur Tünche.

Die Hoffnung der MDA war, dass Diagramme sich auf einer höheren Abstraktionsebene bewegen können als Code, so wie Java auf einer höheren Ebene liegt als Assembler. Doch auch diese Hoffnung hat sich bisher als Fehleinschätzung erwiesen. Der Unterschied im Abstraktionsgrad ist bestenfalls winzig.

Und nehmen wir schlussendlich einmal an, dass eines Tages jemand eine wirklich nützliche Diagrammsprache erfinden wird. Dann werden es nicht Architekten sein, die diese Diagramme zeichnen, sondern Programmierer. Diese Diagramme werden dann einfach zum neuen Code, und Programmierer werden diesen Code zeichnen müssen, weil es letzten Endes immer um Details geht, und es sind die Programmierer, die die Details managen.

A.10  Schlussfolgerung

Seit ich mit dem Programmieren angefangen habe, sind Software-Tools unglaublich leistungsfähig und vielfältig geworden. Mein aktueller Werkzeugkasten ist einfach eine Auswahl dieser Menagerie. Für Quellcodekontrolle nehme ich git, fürs Issue-Tracking habe ich Tracker. Jenkins nehme ich für Continuous Builds, IntelliJ als meine IDE, XUnit für Tests und FitNesse für Komponententests.

Ich habe ein MacBook Pro mit einem Intel Core i7 mit 2,8 GHz und einem matten 17-Zoll-Bildschirm, 8 GB RAM, 512 GB SSD plus zwei Extramonitore.


[1] Diese Bänder konnten nur in eine Richtung gespult werden. Wenn es also einen Lesefehler gab, konnte man das Bandlaufwerk nicht zurückdrehen und noch einmal lesen lassen. Man musste unterbrechen, was man gerade machte, das Band zurück zum Ladepunkt bringen, und dann von vorne anfangen. Das geschah etwa zwei- bis dreimal täglich. Schreibfehler waren ebenfalls sehr häufig, und es gab keine Möglichkeit, wie das Laufwerk dies erkennen konnte. Also beschrieben wir die Bänder immer paarweise und prüften nach Fertigstellung die Paare. War eines der Bänder fehlerhaft, kopierten wir sofort das andere. Wenn beide nicht in Ordnung waren, was sehr selten vorkam, begannen wir mit der ganzen Operation von vorne. So war das Leben damals in den 1970ern.

[2] http://de.wikipedia.org/wiki/ASR-33

[3] Ausradierzeichen waren sehr praktisch für die Bearbeitung von Papierbändern. Diese Ausradierzeichen wurden von der Konvention her ignoriert. Deren Code 0 x FF bedeutete, dass jedes Loch in dieser Zeile des Bands gestanzt war. Das hieß, dass jedes beliebige Zeichen in ein Ausradierzeichen konvertiert werden konnte, indem man es einfach überstanzte. Wenn man also beim Tippen des Programms einen Fehler gemacht hatte, dann konnte man mit der Rückwärtstaste zurückgehen und dann auf Ausradieren drücken. Anschließend fuhr man mit dem Tippen fort.