3. Old-Timer der testgetriebenen Entwicklung: Ron und Steve

Sich mit den Meistern eines Fachs zu unterhalten, bringt immer neue Aha-Erlebnisse. Daher habe ich aus reinem Eigeninteresse einige der TDD-Verfechter der frühen Stunde interviewt. Die Interviews beginnen stets mit einigen Standardfragen und enden mit Themen, die sich auf die Spezialitäten der Interview-Partner beziehen.

3.1 Ron Jeffries

Ron ist ein Pionier des Extreme Programming und Mitautor des agilen Manifests. Seine Aktivitäten kann man auf www.XProgramming.com verfolgen und ihn dort kontaktieren.

Das Interview 1

Wann war dein erster Kontakt mit TDD und was hast du damals davon gehalten?

Ron: Das war 1996 im C3-Projekt. Ich war bereit es auszuprobieren, weil Kent Beck sehr überzeugend sein kann. Vermutlich glaubte ich, dass es nicht viel nutzen würde, weil ich mich bereits für einen großartigen Programmierer hielt.

Was hat dich letztendlich überzeugt, dass testgetriebene Entwicklung ein lohnenswerter Ansatz ist?

Ron: Es tatsächlich zu tun, und dabei genau hinzuschauen. Ich fand, dass es die Arbeitsweise verändert; als ob man Karten richtig stapelt, anstatt sie auf ihre Kanten zu stellen.

Was hat sich seit den frühen Tagen in der Art und Weise verändert, in der du TDD praktizierst und anderen beibringst?

Ron: Ich glaube, ich versuche es weniger anzupreisen, weil ich alles weniger anpreise als früher. Ich zeige den Leuten, was ich tue, erkläre, wie ich es tue und warum, und überlasse ihnen den Rest.

Ist deine TDD-Technik eine andere als zu Beginn? Sind deine einzelnen Schritte größer oder kleiner geworden?

Ron: Meine Schritte werden immer kleiner. Natürlich denke ich immer nach, aber ich lasse den Code mir sagen, was ich tun muss, nicht irgendwelche Theorien über Design.

Gehst du an Abhängigkeiten mit anderen Werkzeugen und veränderter Taktik heran? Wie z.B. Test-Doubles und Mocks?

Ron: Als Mitglied der “klassischen TDD-Schule” verwende ich normalerweise keine Test-Doubles, höchstens um mich von einer Datenbank zu entkoppeln oder um eine größere Objektmenge darzustellen. Stattdessen lasse ich Objekte an Ort und Stelle wachsen - und teste sie während sie größer werden.

Gibt es Situationen, in denen du TDD nicht für den richtigen Entwicklungsansatz hältst? Und wenn ja, welche Techniken und Ansätze empfiehlst du in diesen Fällen?

Ron: Ich finde TDD schwierig, wenn ich Software schreibe, die die echte Welt direkt manipuliert. Wenn Systemaufrufe Gegenstände bewegen oder anderes “physisches” Verhalten auslösen, dann fallen mir Tests mit TDD schwer, da es keine Stelle gibt, an der man dieses Verhalten unterbrechen und überprüfen könnte, ohne dass es tatsächlich passiert.

Ich finde TDD auch dann schwierig, wenn es noch kein entsprechendes Framework gibt und wenn das Basissystem zu nackt ist, um schnell eines zu bauen, beispielsweise ohne Reflection und ohne Objekte. Dann mache ich sehr kleine Schritte und drucke die Zwischenergebnisse aus. Häufig überprüfe ich sie dann lediglich visuell; selten schreibe ich dann einen kleinen Test im TDD-Stil. Einen Debugger verwende ich jedoch nie, in den meisten Umgebungen wüsste ich nichtmal, wie er funktioniert.

Was ist deiner Meinung nach die Bedeutung von testgetriebener Entwicklung in der heutigen Welt - mit Lean Startups, funktionaler und nebenläufiger Programmierung, Continuous Delivery und den allgegenwärtigen Mobilgeräten?

Ron: TDD ist immer noch die beste Art zu programmieren, die ich kenne. Wo sie eingesetzt werden kann - also fast überall - hilft TDD den Code gleichmäßig wachsen zu lassen; sie führt meist zu einfachem aber gutem Design, und sie hält mich davon ab, Karten auf ihre Kante zu stellen.

Herzlichen Dank, Ron, für die Beantwortung der Fragen!

Persönliches Fazit

Trotz mehrerer Jahrzehnte an Programmiererfahrung gibt es für Ron keinen besseren Entwicklungsansatz. Das macht mir noch einmal deutlich, dass alternative Entwicklungsansätze zu TDD, die ähnliche Ergebnisqualität liefern und gleichzeitig eine feine Kontrolle über die Entwicklung erlauben, nicht auf der Straße liegen.

3.2 Steve Freeman

Steve ist der prominenteste Vertreter der “London School of TDD”, auch wenn er behauptet, dass diese gar nicht existiert. Zusammen mit Nat Pryce hat er das Buch “Growing Object-Oriented Software, Guided by Tests” geschrieben. Dies ist eines der einflussreichsten TDD-Bücher der vergangenen Jahre. Steve twittert als @sf105 und kann über http://www.higherorderlogic.com kontaktiert werden.

Das Interview2

Wann war dein erster Kontakt mit TDD und was hast du damals davon gehalten?

Steve: Das war irgendwann 1997 oder 1998. Ich arbeitete bei OTI in London und wir verfolgten die anschwellende Diskussion um das C3-Projekt auf dem C2-Wiki. Zunächst war unsere allgemeine Reaktion “Das kann überhaupt nicht klappen”, aber wir haben immer weiter Dinge ausprobiert und es stellte sich heraus, dass sie doch funktionierten. Außerdem war Kent Beck in jenem Jahr Sprecher auf der SPA Konferenz, so dass wir mehr darüber herausfinden konnten, wie die diversen Praktiken tatsächlich durchgeführt wurden.

Was hat dich letztendlich überzeugt, dass testgetriebene Entwicklung ein lohnenswerter Ansatz ist?

Steve: Ausprobieren und feststellen, dass es für mich hilfreich war. Außerdem gab es ein paar schöne Gegenbeispiele, bei denen ein Teammitglied sich die Nacht um die Ohren schlug, um etwas “hinzubekommen”, was dann das Team einen ganzen Vormittag kostete, die eingebauten Fehler wieder zu entfernen.

Was hat sich seit den frühen Tagen in der Art und Weise verändert, in der du TDD praktizierst und anderen beibringst?

Steve: Einiges ist reine Technik, wie etwa das Zerschneiden eines Feature in Inkremente und das Arbeiten auf unterschiedlichen Testebenen. Heutzutage verwende ich viel Mühe darauf, die Tests lesbar und ausdrucksstark zu gestalten, anstatt möglichst auch das kleinste Detail zu testen. Eigentlich war das schon immer so, aber heute ist es meine oberste Priorität. Auch habe ich jetzt ein besseres Verständnis, wie ich TDD als “Denkwerkzeug” einsetzen kann, um meine Ideen klarer zu machen bevor ich sie in Code festhalte. Ich benutze mittlerweile auch System-Level-Tests, um das Grobdesign zu beeinflussen. Und schließlich habe ich begriffen, dass TDD eine tiefgehende Technik ist, wie alles bei der Programmierung. Ein paar Tage Workshop und ein Buch durchblättern ist nichts als eine kleine Kostprobe.

Gibt es Situationen, in denen du TDD nicht für den richtigen Entwicklungsansatz hältst? Und wenn ja, welche Techniken und Ansätze empfiehlst du in diesen Fällen?

Steve: Nat Pryce zitiert gerne Manny Lehmanns Softwarekategorien. Einige Arten “algorithmischer” Systeme (P-Systeme) sollten gelöst werden, indem man intensiv nachdenkt – auch wenn ich glaube, dass TDD selbst hier zur Implementierung beitragen kann. Ich arbeite jedoch meist an “unordentlichen” E-Systemen, die sich mit ihrer Umgebung verändern und keine sauberen Anforderungen haben. Dies ist der Ort, an dem TDD im weiteren Sinne besonders gut passt.

Andere Ausnahmen sind Systeme, die schnell zusammengesteckt werden um etwas zu beweisen, oder Systeme, mit denen der Programmierer ein neues Gebiet erforscht. Ich denke da u.a. an Sam Aarons live Musik-Programmierung. Außerdem gibt es eine neue Systemgeneration mit “Testen in Produktion”, bei denen die Produktionsinfrastruktur so robust ist, dass die Entwickler risikolos mit dem echten System experimentieren können. Entscheidend ist dabei, dass man sich bewusst ist, was ich priorisiere und welche Risiken ich möglicherweise anhäufe. Kent Beck benutzt die Unterscheidung: Priorisierung für geringe Wartezeit (engl. low latency) versus ausdauerndem und gleichmäßigem Durchsatz (engl. sustained throughput) von neuen Funktionen.

Egal welche Techniken ich einsetze, ich halte es gewöhnlich für wertvoll innezuhalten und darüber nachzudenken, was ich als Ergebnis möchte, bevor ich mit dem Coding beginne; auch wenn ich diese Überlegungen dann nicht automatisiere.

Was ist deiner Meinung nach die Bedeutung von testgetriebener Entwicklung in der heutigen Welt - mit Lean Startups, funktionaler und nebenläufiger Programmierung, Continuous Delivery und den allgegenwärtigen Mobilgeräten?

Steve: Das ist eine ordentliche Liste, und ich bin nicht sicher, ob sie tatsächlich bereits die Mehrheit der Softwareumgebungen betrifft. Die Kurzfassung: Es scheint mir immer eine gute Idee zu sein, irgendeine Art von Regressionstests zu haben, insbesondere wenn ich schnell und sicher vorankommen möchte. Unter dieser Voraussetzung fällt es mir leichter, die Tests vorher zu erstellen, denn in der Praxis werde ich es danach nicht mehr tun. Es existieren einige hochentwickelte Umgebungen, in denen das nicht zutrifft, dennoch würde ich das Risiko nicht eingehen, bevor ich nicht genau verstehe, was ich aufgebe und wie ich das kompensieren kann.

Du bist ein prominenter Vertreter der “London school of TDD”, welche den Einsatz von Mock-Objekten betont, um dadurch die Verträge (engl. collaboration contracts) zwischen Objekten festzulegen, anstatt lediglich das Verhalten eines isolierten Objekts zu testen. Würdest du sagen, dass diese Kollaborationstests wertvoller sind als zustandsbasiertes (engl. state-based) Testen? Was entgegnest du Kritikern, die Mock-Objekte ablehnen, weil sie nicht “die echte Integration” testen?

Steve: Ich bin es mittlerweile leid, diese Diskussion mit Leuten zu führen, die unser Buch nicht gelesen haben und nicht verstehen, wovon wir wirklich reden. Ich priorisiere nicht die eine Testart grundsätzlich vor der anderen, sondern ich priorisiere die Art, die auf das zu testende Objekt am besten passt. Habe ich ein Objekt mit eigenem Verhalten und ich praktiziere “Tell, Don’t Ask”-Design, dann kann ich nur die Interaktionen testen. Für andere Arten von Objekten trifft das nicht zu.

Das Argument zur “echten Integration” trifft dann zu, wenn ich Mocks einsetze, um gegen eine externe Schnittstelle zu testen, was ich persönlich nie tue - wir raten auch bereits seit mehr als 10 Jahren davon ab. Für diesen Fall benutze ich Integrationstests.

Der Punkt, den ich allerdings überhaupt nicht begreife, und ich sehe ihn auch bei sehr guten Entwicklern, ist die Unfähigkeit, mit vorab spezifizierten Mock-Constraints umzugehen; diese Unfähigkeit hat u.a. Werkzeuge wie Mockito hervorgebracht. Das Problem wird verschwinden, sobald Java Closures besitzt. Ich habe aufgehört dagegen zu kämpfen und nutze es als Wettbewerbsvorteil. Wenn jemand wirklich zuhören möchte, dann führe ich gerne eine zivilisierte Diskussion.

Herzlichen Dank, Steve, für die Diskussion!

Persönliches Fazit

Die Ideen hinter Manny Lehmanns Laws of Software Evolution waren für mich neu und können dabei helfen, die Anwendbarkeit testgetriebener Entwicklung auf ein konkretes Problem zu beurteilen. Der letzte Teil des Interviews greift einem Thema vor, dem in diesem Buch mehrere Kapitel gewidmet sind: Abhängigkeiten und wie man mit ihnen umgeht. Es lohnt sich daher sicherlich, das Interview nach der Lektüre der entsprechenden Kapitel nochmals zu lesen.