TDD oder Der Weg ist das Ziel

Es gibt viele Blogs über TDD? und Unit Testing. Welche Vorteile es mit sich bringt, welche Nachteile es mit sich bringt, warum man es machen sollte oder warum auch nicht.

Die Entwickler(innen) die ihre Projekte per TDD entwickeln oder Unit Testing praktizieren scheinen immer noch eine Minderheit zu sein. So schien es mir wenigstens auf der IPC, Berlin im Juni 2013 oder bei der ZendCon Europe, Paris im November 2013.

Woran kann das liegen?

Eine einfache Frage auf die es keine einfache Antwort gibt. Zu vielschichtig sind die Umstände und Einflüsse die einem Entwickler im täglichen Geschäft zu schaffen machen.

Ich werde in diesem Post meinen Weg von einem gestressten Entwickler zu einem entspannten und überzeugten TDD und Unit Test Evangelisten aufzeigen.

Der Anfang

Ich arbeite seit über 8 Jahren in einem projektgetriebenen Umfeld. Zeit ist Geld, es ist wichtig zu liefern - und das schnell. Am Anfang waren die Projekte eher klein und überschaubar. Überwiegend One-Man Shows um möglichst viele Aufträge erledigen zu können.

Unit Testing fand in diesem Umfeld nicht statt. Es ging auch ohne, und das eine ganze Zeit lang.

Aber irgendwann fängt es an. Ein schleichender Prozess dessen Auswirkungen sich aufsummiert und irgendwann nicht mehr verwaltbar ist. Je mehr Projekte erledigt wurden und je umfangreicher die Projekte wurden, umso mehr Wartung, Pflege und Erweiterungen kamen. Hier mal schnell was erweitert, dort mal was reingehackt - teilweise direkt am offenen Herzen.

Die Anzahl der Bälle die gleichzeitig in der Luft gehalten werden mussten wurde irgendwann absurd.

Die Code Basis wurde langsam aber sicher immer schlimmer. Die Tage wurden länger, die Zeit ein neues Feature zu implementieren wurde länger - teilweise sogar unmöglich. Ein gefixter Bug hatte auch schon mal neue Fehler zur folge, weil auf dem Fehler Features aufgesetzt wurden - schön ist was anderes.

Ein Faktor der aber noch schwerer wiegt, und den man erst im Rückblick und mit Abstand erkennt: Man verliert Reputation und Vertrauen.

Der Wendepunkt

Irgendwann kommt man an den Punkt, an dem man merkt dass es so nicht weitergehen kann. Man braucht eine Lösung, irgendetwas das einem hilft dem Chaos Herr zu werden. Es gibt nicht die "Eine" allumfassende Lösung. Für mich und das Team mit dem ich zusammenarbeite wollten wir eine Lösung finden die uns in Zukunft die Arbeit erleichtern sollte.

Unser Ansatz war: Unit Testing und (nach Möglichkeit) Test Driven Development - bei allen neuen Projekten.

Wir haben schon längere Zeit mit dieser Option geliebäugelt, aber es gab einige Hindernisse und Probleme die dann doch immer dafür gesorgt haben es sein zu lassen. Was das war, und wie es gelöst wurde siehst du etwas weiter unten.

Wie fängt man an?

Aller Anfang ist bekanntlich schwer. Vor allem bei einem Werkzeug von dem man nicht so richtig weiß wie man am Besten anfängt. Das Internet ist voller guter und schlechter Beispiele, es gibt Bücher und Leute die sich damit auskennen.

Es gibt nichts gutes, außer man tut es.

Erich Kästner

Wir haben ein Projekt ausgewählt das einen überschaubaren Aufwand hatte, und das für einen Entwickler ausgelegt war. Der Aufwand bewegte sich in der initialen Schätzung - wenn alles glatt läuft, und die Anforderungen so bleiben - bei 22 Personentagen. Das Ziel war eine Schnittstelle für eine iOS-, Android- und Web-App bereitzustellen. Die Schnittstelle dient als mittler zwischen diversen anderen Schnittstellen, und bot somit eine mehr als ausreichende Komplexität.

Was es galt festzustellen:

  1. Können wir Unit Testing in adäquater Zeit lernen und umsetzen?
  2. Können wir solidere Software bauen, Features einfacher implementieren?
  3. Werden wir langsamer?

Hatten wir einen Plan B? Nicht wirklich.

Der Weg

Es ist nicht genug, zu wissen, man muß auch anwenden; es ist nicht genug, zu wollen, man muß auch tun.

Johann Wolfgang von Goethe

Alleine die Erwähnung von Unit Tests kann bei dem Einen oder Anderen schon ausreichen in Verteidigungsposition zu gehen. Ein paar der Aussagen - ob nun Management/Business oder Entwickler - auf die man trifft:

  1. Dafür ist keine Zeit
  2. Dafür werden wir nicht bezahlt
  3. Das ist zu aufwändig
  4. Dafür haben wir ne QA
  5. Für meine Sachen brauch ich das nicht

Die Fragen und die Aussagen sind durchaus gerechtfertigt. Wie geht man damit um?

Man kann versuchen sich den Mund fusselig zu reden, Studien zu präsentieren, auf die Geschichte in der Softwareentwicklung verweisen. Das kann funktionieren - je nachdem wer einem gegenüber sitzt - muss aber nicht.

Und nun?

Nicht drüber sprechen, einfach machen!

Da es das erste Projekt war das so entwickelt wurde blieben Probleme nicht aus. Der Anfang war etwas holperig, es war hier und da schwierig die Tests zu schreiben und Testdaten zu erzeugen.

Die Tests sind nicht aller erste Sahne, aber sie erfüllen ihren Zweck.

Das Ergebnis

Das Resultat war für uns wegweisend - es ist jetzt knapp 2 Jahre her.

Welches Ergebnis haben wir mit dem "Test-Projekt" erzielt?

  1. Können wir Unit Testing in adäquater Zeit lernen und umsetzen?
    Klares Ja. Wir benutzen PHPUnit, und bleiben damit in der gewohnten Sprache. Tests schreiben wurde mit jedem Test, und jedem Tag ein wenig besser.

  2. Können wir solidere Software bauen, Features einfacher implementieren?
    Klares Ja. Durch die Testbarkeit war die Kopplung des Codes nicht so starr wie wir es vorher hatten. Mit den Tests wurde es deutlich einfacher und sicherer neue Features einzubauen.

  3. Werden wir langsamer?
    Der Anfang war langsamer. Die Geschwindigkeit am Ende des Projektes war ungewöhnlich hoch. Neue Features einzubauen machte keine Probleme und sorgte nicht für Frust, sondern machte wieder Spaß.

Wie bei allen Projekten änderten sich die Anforderungen und der Umfang. Das stellte diesmal für uns kein Problem dar. Wir waren auch zeitlich im Rahmen - wir waren nicht langsamer.

Aber eine weitere wichtige Frage die nicht gestellt wurde: Kann man die Defektrate senken?

Dazu ein paar Zahlen:

  • ~3.2 kLOC Business Code (mittlerweile ~5.3kLOC)
  • ~3.2 kLOC Test Code (mittlerweile ~4.8kLOC)
  • Bugs die in der Entwicklung aufgetreten sind: 6
  • Minor Bugs im Betrieb während der ersten 18 Monate: <5
  • Major Bugs im Betrieb während der ersten 18 Monate: 0
  • Neue Features während der ersten 18 Monate: 80+

Das ist ein mehr als hervorragendes Ergebnis für das allererste Projekt das wir so entwickelt haben.

Fazit

I'm not a great programmer; I'm just a good programmer with great habits.

Kent Beck

Auch wenn die Tests im Rückblick noch nicht die Besten waren, waren sie so gut ein Projekt dieser Qualität auf die Beine zu stellen.

Auf Basis dieses "Experiments" wurden alle weiteren neuen Projekte nur noch mit Unit Tests implementiert. Die hohe Qualität der Software hat nicht nur Einfluss auf den Stresslevel. Wartung, Betrieb und Erweiterbarkeit der Software gestaltet sich wesentlich einfacher und sicherer.

Eine niedrige Defektrate bedeutet gleichzeitig auch einen monetären Gewinn. Weniger Fehler, die zusätzlich noch leichter zu beheben sind bedeuten mehr Zeit für neue Dinge. Die Abwärtsspirale in der wir uns befunden haben hat sich umgekehrt.

Würde ich Unit Testing und TDD weiterempfehlen? Unbedingt.

Wartet nicht drauf dass euch das Management oder der Vorgesetzte grünes Licht gibt - handelt selbst. Die Veränderung muß von uns kommen.



Bücherempfehlung



Studien