Einer der Begriffe, die bei Agilen Softwareentwicklungsprozessen immer wieder zu hören sind, ist „Definition of Done“ (DoD). Man soll also vorher definieren, was man unter „fertig“ versteht. Das hört sich erstmal trivial an. Und der triviale Grund, dass man ansonsten aneinander vorbei redet, leuchtet auch jedem ein.
„Ist Feature X jetzt endlich fertig?“
„Ja, hab ich gestern eingecheckt.“
„Dann können wir morgen also deployen.“
„Neinnein, da muss noch die QA drüber. Da ist noch nix getestet.“
„Ist Feature Y jetzt endlich fertig?“
„Fast. Zu 90% ist es fertig. Ich muss nur noch…“
Wenn man einmal definiert, was „fertig“ bedeutet, kommt es zu weniger Missverständnissen. Mal ganz davon abgesehen, dass man so auch leichter dieses „fast fertig“ ausmerzen kann. Entweder ist ein Feature „done“ oder eben nicht. Zu 90% fertig bedeutet ja meist, dass noch (weitere) 90% vor einem liegen. Das ist die so genannte 90-90 rule. Und diese ist nur zu oft wahr. Auch, wenn mans vielleicht nicht wahr haben will (mich teilweise auch noch eingeschlossen; ich arbeite daran).
Das ist alles klar und allgemein bekannt. Aber es gibt noch einen anderen Grund für eine DoD: Angenommen man steht unter Zeitdruck (und bei Sprints/Iterationen von zwei Wochen Länge, ist das schnell passiert). Bis Morgen Mittag um 12 muss das Feature fertig sein. Wie schnell ist es da passiert, dass man das nötige Refactoring doch sein lässt und vielleicht auch nur halbherzig testet und dokumentiert — nur um das Feature „fertig“ zu kriegen.
Genau genommen ist besagtes Feature aber noch nicht fertig, denn es gibt noch eine gewisse Menge Arbeit, die „für dieses Feature“ noch getan werden muss. Und dann ist man auch schon in der nächsten Iteration, hat neue Aufgaben und das Feature bleibt schlecht getestet und das nötige Refactoring wird auch nicht gemacht. Probleme häufen sich auf, es gibt ne Menge Arbeit, die keiner sieht, aber dennoch getan werden muss. Kurz: Man schludert beim Programmieren.
Außerdem neigt man zu „Failure Mode Programming“ [1]. Anstatt sauber zu programmieren und zu testen, fixt man nur Bugs und guckt, dass man die Software irgendwie ans Laufen kriegt. Man ist quasi im „Fehler- bzw. Bugfix-Modus“ statt im normalen „Programmiermodus“. Fast unbewusst kehrt man zum altbekannten „Code and Fix“ zurück, das man doch eigentlich nicht mehr machen wollte. Zeitdruck drängt einen in diese Richtung.
Aber eine klare Definition of Done hilft, sich davor zu schützen. Wenn das Refactoring und eine gewisse Testabdeckung zur DoD dazu gehört, dann ist ein Feature, das nicht sauber entwickelt wurde, dem Tests fehlen und für das noch kein Refactoring gemacht wurde, eben noch nicht fertig. Auch wenn es „im Prinzip läuft“.
Bei der Summerschool „Agile Software Development“ hab ich das genau so erlebt. Wir hatten Sprints von etwa zwei Stunden Länge. Und uns fehle eine DoD. Und obwohl ich normalerweise eher einer bin, der zu viel als zu wenig Wert auf sauberen Code legt, bin auch ich in den „Failure Mode“ zurück gefallen. Ich denke, wenn wir klar kommuniziert hätten, was „fertig“ bzw. „done“ heißt, wären wir unterm Strich schneller gewesen. Failure Mode Programming reduziert Codequalität und damit auch die Produktivität.
Kaum hatten wir uns mal in Ruhe hingesetzt und sind den Code Zeile für Zeile durchgegangen, anstatt nur zu debuggen, hatten wir den Fehler auch schon gefunden und dabei auch noch einige Unsauberkeiten ausgebessert. Ein Debugger ist ein tolles Werkzeug und ich verzichte nur sehr ungern darauf, aber letztendlich ist einmal sauber programmieren schneller, als schnell programmieren und dann debuggen.
Das selbe hätte ich zwar auch schon vorher gesagt, aber echter Zeitdruck, macht die Situation anders. Man muss sich das wohl wirklich jedes Mal wieder vor Augen führen. Und eine DoD kann IMHO dabei helfen. An weiteren Maßnahmen arbeite ich noch.
[1] Irgendwo hab ich den Begriff mal gelesen oder zumindest einen ähnlichen. Ich finds gerade nicht. Zur Not ist es eben eine Eigenkreation… 😉