Das Ticket war eine Zeile: “Blogbeiträge, die älter als zwei Jahre sind, sollen aus der Übersicht verschwinden.” Der Agent hatte es gelesen, die Stelle im Code gefunden, an der die Übersichtsseite ihre Beiträge zusammenstellt, und dort einen Filter auf das Veröffentlichungsdatum ergänzt. Die Tests liefen durch, die Vorschau zeigte genau das, was verlangt war - alte Beiträge, aus der Liste gefallen. Der Pull Request war technisch tadellos.
Er war trotzdem falsch. Der Filter saß in der gemeinsamen Abfrage, aus der sich sowohl die Übersichtsseite als auch die Sitemap speisten. Ein Beitrag, der aus der Liste verschwand, verschwand damit auch aus der Sitemap - und ein paar Wochen später aus dem, was Suchmaschinen von der Seite noch kannten. Niemand hatte das gewollt, und niemand hatte es aufgeschrieben. Wer das Ticket formuliert hatte, dachte an eine aufgeräumte Übersicht für Besucher. Dass alte Beiträge trotzdem unter ihrer eigenen URL erreichbar und auffindbar bleiben sollten, stand nirgends - es war so selbstverständlich, dass es niemand für erwähnenswert hielt.
Genau an dieser Stelle wird sichtbar, was Automatisierung tatsächlich tut. Sie schreibt nicht weniger menschliche Arbeit. Sie verschiebt sie an eine andere Stelle im Prozess.
Was tatsächlich verschwindet
Der Teil, der ersetzt wird, ist real, und es lohnt sich, ihn nicht kleinzureden. Die Stelle im Code finden, an der eine Änderung ansetzen muss. Die Schreibweise, mit der ein Filter formuliert wird. Den Test dazuschreiben, der die neue Regel absichert. All das war vor drei Jahren mühsame Handarbeit und ist heute in Minuten erledigt, oft besser dokumentiert und konsistenter benannt, als es unter Zeitdruck von Hand entstanden wäre.
Das ist kein kleiner Gewinn, und wir tun niemandem einen Gefallen, wenn wir ihn kleinreden, um die Erzählung von der unverzichtbaren menschlichen Arbeit zu retten. Ein großer Teil dessen, was Softwareentwicklung über Jahrzehnte mühsam gemacht hat, war genau dieses mechanische Übersetzen einer Absicht in eine bestimmte Syntax. Diese Übersetzung kann eine Maschine inzwischen zuverlässig übernehmen.
Was an die erste Stelle rückt
Was nicht kleiner wird, ist die Arbeit, den Auftrag so zu formulieren, dass die Übersetzung überhaupt trifft, was gemeint war. “Aus der Übersicht verschwinden” ist ein Satz, den ein Mensch beim Lesen mit einem ganzen Kontext auffüllt, den er nie ausspricht: dass die Beiträge weiter existieren, dass ihre URLs weiter funktionieren, dass die Sitemap unberührt bleibt, weil das eine andere Frage ist als die Übersicht. Ein Modell füllt diesen Kontext nicht auf. Es liest den Satz, findet die naheliegendste Implementierung, die ihn erfüllt, und hat damit formal recht.
Das ist keine Beschwerde über die Qualität des Modells. Es ist eine Beschreibung dessen, wofür Sprache in einem Ticket eigentlich gebraucht wird. Ein gutes Ticket sagt nicht nur, was passieren soll. Es grenzt ab, was nicht mitgemeint ist - und genau dieses Abgrenzen ist die Aufgabe, die jetzt am Anfang steht, wo früher das Nachdenken über die Implementierung stand. Der Aufwand ist nicht verschwunden. Er ist von “wie schreibe ich diesen Filter” zu “was genau meine ich mit verschwinden” gewandert, und diese zweite Frage lässt sich nicht outsourcen, weil sie erfordert, den eigenen Wunsch vollständig zu Ende zu denken, bevor man ihn aufschreibt.
Die zweite Stelle: beurteilen, nicht nur lesen
Die zweite Verschiebung passiert danach, beim Ergebnis. Ein Pull Request, der plausibel aussieht, ist etwas anderes als einer, der tut, was gemeint war, und der Unterschied liegt selten im Diff selbst. Der Filter im Beispiel oben liest sich beim Review einwandfrei - eine Zeile, die Beiträge nach Datum ausschließt, genau dort, wo die Übersicht ihre Liste zusammenstellt. Wer das Diff liest, sieht Code, der exakt das tut, was das Ticket verlangt hat. Um zu sehen, dass er zu viel tut, muss man wissen, dass diese Abfrage auch die Sitemap speist - ein Wissen, das nicht im Diff steht und nicht im Ticket, sondern nur im Kopf von jemandem, der die Architektur der Seite kennt.
Das ist die Beurteilung, die am Ende stehen muss, und sie ist etwas anderes als Codereview im hergebrachten Sinn. Codereview fragt, ob eine Änderung sauber geschrieben ist. Diese Beurteilung fragt, ob sie das tut, was tatsächlich gewollt war, einschließlich der Teile, die niemand für nötig hielt aufzuschreiben. Diese Frage kann nur jemand beantworten, der den Kontext hat, den das Ticket nicht enthält - und dieser Jemand ist, jedenfalls heute noch, ein Mensch.
Was davon besser wird und was schlechter
Ehrlich gesagt, wird nicht alles daran leichter. Ein Ticket schreiben zu müssen, das wirklich präzise ist, ist harte Arbeit, und sie war vorher optional, weil ein Mensch, der die Umsetzung übernahm, Lücken im Auftrag stillschweigend mit eigenem Urteil gefüllt hat. Diese stille Korrektur fällt jetzt weg. Ein vages Ticket erzeugt nicht mehr automatisch ein vernünftiges Ergebnis, weil niemand mehr zwischen Auftrag und Umsetzung sitzt, der die Lücke aus Erfahrung schließt. Wer das nicht bemerkt, bekommt schlechtere Ergebnisse als früher, nicht bessere - und schiebt es dann fälschlich auf das Modell.
Besser wird dagegen, wie ehrlich Teams über ihre eigenen Anforderungen werden müssen. Ein Ticket, das ein Modell zuverlässig richtig umsetzen soll, zwingt dazu, vorher zu klären, was man eigentlich will, statt das im Verlauf der Umsetzung nachträglich zu entdecken. Das ist unbequem und meistens ein Gewinn, weil die Klärung ohnehin fällig war - sie fand vorher nur später statt, verteilt über mehrere Rückfragen und einen zweiten Anlauf.
Und schlechter wird, mit welcher Leichtigkeit ein sauber aussehendes Ergebnis durchgewunken wird. Ein Diff, das genau das enthält, was das Ticket verlangt hat, sieht erledigt aus. Ob es das ist, entscheidet sich woanders - in der Frage, ob jemand das laufende System angeschaut hat, nicht nur den Text der Änderung. Diese Prüfung lässt sich nicht automatisieren, ohne dass man beim nächsten Ticket vor demselben Problem steht: Wer beurteilt, ob die Beurteilung korrekt war?
Warum ans Ende
Der Mensch gehört nicht an den Anfang des Prozesses, weil dort inzwischen viel schneller gearbeitet werden kann, ohne dass am Ergebnis etwas verloren geht. Er gehört auch nicht in die Mitte, wo er nur noch zusieht, wie ein Modell tut, was im Ticket steht. Er gehört ans Ende, an die Stelle, an der jemand fragt, ob das, was tatsächlich passiert ist, mit dem übereinstimmt, was gemeint war - eine Frage, die den ganzen Kontext eines Vorhabens braucht, nicht nur den Text, der davon aufgeschrieben wurde.
Das ist keine vorübergehende Aufgabe, die verschwindet, sobald die Modelle noch etwas besser werden. Es ist die Aufgabe, die übrig bleibt, wenn alles andere gelöst ist.