Gelebte inkrementelle Dekomposition
Neulich war große Freude. Ein Produktentwicklungsteam eines Kunden zeigte mir, wie es meinen Vorschlag eines anderen Umgangs mit Anforderungen umsetzt - und dadurch flüssiger arbeitet.
Inkrementelle Analyse
Mein Vorschlag war und ist, Anforderungen des Kunden bzw. die User Stories eines Product Owners nach einem Schema "zu zermahlen", um für die weitere Entwicklung sehr präzise Ausgangspunkte zu bekommen.
Ausführlicher habe ich dieses Schema in einem früheren Artikel beschrieben. Deshalb skizziere ich es hier nur noch und stelle es in einen Prozesszusammenhang.
Für mich sieht ein Teil des Softwareproduktionsprozesses so aus:
Ein Strom von unstrukturierten Anforderungen wird von einem Product Owner im Rahmen eines so genannten Story Development durchgekaut und in User Stories transformiert. Die sind klein, konkret, wertorientiert, priorisiert.
Allerdings sind User Stories rein aus der Sicht von Kunde/Anwender formuliert. Die Programmierung kann sie nicht einfach implementieren. Vielmehr muss darauf eine Vorverarbeitung stattfinden.
Entwickler (und Tester) sitzen dafür zunächst mit dem Product Owner zusammen und analysieren die User Stories. Bisher hat ja nur der Product Owner verstanden, was zu tun ist. Dieses Wissen muss in die Köpfe der Programmierer übertragen werden. Das bedeutet, die Welt des Problems muss an die Welt der Lösung angeschlossen werden. Es müssen Bezüge hergestellt werden, ein Mapping stattfinden.
Mit meinem Ansatz plädiere ich dafür, die User Stories "in einen Problemtrichter zu stopfen", aus dem unten einzelne Funktionen mit zugehörigen Akzeptanzkriterien heraustropfen.
User Stories stellen die Anforderungen in Form von Inkrementen vor, d.h. für den Kunden wertvolle Zuwächse an Funktionalität oder Effizienz. Slices sind Inkremente mit konkretem Bezug zur Welt der Codierung, d.h. der Lösung.
Die Problemanalyse transformiert einen Strom von User Stories also in einen Strom von Slices unterschiedlicher Dicke. Hier die Liste der wichtigsten Slices mit den ihnen entsprechenden Programmierartefakten (Module):
- Anwendung = Bibliothek
- Dialog = Klasse
- Interaktion = Funktion
- Feature = Funktion
Jede User Story entspricht dann in der Hierarchie der Slices einem oder mehreren Pfaden der Form Anwendung/Dialog/Interaktion/Feature. Das ist für die weitere Programmierung sehr, sehr viel konkreter, als eine User Story. Die Programmierung fühlt sich auf diese Weise weniger allein gelassen mit Verständnis und Übersetzung von Anforderungen. Ja, die Programmierung bekommt durch die gemeinsame Problemanalyse mit dem Product Owner sogar schon konkrete Hinweise auf eine minimale Modularisierung des Codes. Und die spiegelt dann auch noch das agile Vorgehen wider.
Während üblicherweise User Stories nach der Implementation nicht mehr im Code zu erkennen sind, bleiben bei diesem Vorgehen Inkremente als Artefakte im Code erhalten. Das ist von unschätzbarem Wert für die Nachvollziehbarkeit und Verständlichkeit von Code.
Der ursprüngliche Strom von Anforderungen wird also in zwei Schritten zerlegt in Inkremente (inkrementelle Dekomposition):
- Story Development -> User Stories
- Problemanalyse -> Slices
Beide zusammen dienen der Qualitätssicherung des Input in die weitere Programmierung. Das ist wichtig, da einer der häufigsten Engpässe bei der Softwareproduktion die Implementation oder die anschließende QA ist. Hohe Inputqualität für den Engpass ist Voraussetzung für hohe Qualität seines Output. Und die ist wichtig, damit der Engpass später nicht mit Nachbesserungen belastet wird.
Soweit die Theorie. Jetzt die Praxis.
Im realen Projekt
Als Trainer in Sachen flüssige Softwareproduktion und Clean Code Development stelle ich diese Vorgehensweise vielen, vielen Entwicklern vor. Wir üben sie dann tapfer in Workshops. Doch die Übertragung solcher "Theorie" in den Arbeitsalltag fällt den Teilnehmern immer wieder sehr schwer. Über die Gründe kann man diskutieren und lamentieren - aber nicht heute. Heute möchte ich zur Abwechslung zeigen, wie der Transfer eben auch klappen kann.
Das Team bei meinem Kunden besteht im Wesentlichen aus 2 Entwicklern, 3 Testern und 1 Product Owner. Beide Entwickler hatten an 2 Schulungstagen der Clean Code Developer School teilgenommen, an denen wir uns auf den Umgang mit Anforderungen konzentriert hatten. Dann am Ende des dritten Schulungstages luden sie mich ein, sich ihre Umsetzung des Lernstoffes in ihrem team room einmal anzusehen.
An der Wand sah ich dort diesen Notizenbaum:
Die Anwendung, an der das Team arbeitet, steht außer Frage. Die muss nicht explizit modelliert werden.
Der Dialog, auf den sich die (derzeit) zu realisierenden User Stories beziehen, steht ebenfalls außer Frage. Die ganze Wand konzentriert sich auf diesen Dialogentwurf:
Aus diesem Grund ist der Dialog auch nicht an der Wand zu sehen. Das finde ich verständlich, aber meine Empfehlung ist, ihn dennoch dort ebenfalls zu visualisieren. Dadurch wird jedes Denken über Slices konkreter. Bei Diskussionen kann man leichter Bezug nehmen, um über Interaktionen und Features zu sprechen. Niemand muss im Zweifelsfall in irgendwelchen Dokumenten nach dem aktuellen Stand des Dialog-Layouts suchen.
Aber auch ohne Dialog finde ich die Darstellung an der Wand klasse. Dort sind nämlich die von mir vorgeschlagenen Slices systematisch als Baum zu sehen:
- Quer über die Wand stehen grüne Karten für Interaktionen des Dialogs. Jede lässt sich einem Button oder dem Klick auf eine Liste usw. zuordnen.
- Senkrecht stehen orange und gelbe für Features der jeweiligen Interaktion. Die Darstellung der Feature-Hierarchie ist an der Wand leider begrenzt. Mit Farben wurden zwei Ebenen unterschieden und es gibt eine gewisse physische Unterordnung. Letztlich kommt hier der Umgang mit Kärtchen aber an seine Grenzen. Doch das Team ist kreativ mit seinen Mitteln umgegangen. Super!
An diese Wand kann ich herantreten, eine beliebige Karten auswählen und bin sicher, dafür eine Entsprechung im Code zu finden. Da es sich um Interaktionen und Features handelt, gibt es für jede 1 Funktion im Code.
Das ist die Sicht der Entwickler. Gleichzeitig stellt jede Karte aber auch noch Wert für den Product Owner dar! Alle Karten repräsentieren Inkremente. Zu allen Karten kann der Product Owner Feedback geben, ob das gewünschte Verhalten schon nach seinem Geschmack umgesetzt wurde.
(Zu dieser Regel gibt es nur eine Ausnahme: Die zweite grüne Karte von Links steht nicht für eine Interaktion sondern für die Datenstruktur des Dialogs, d.h. für die Steuerelemente mit den zugehörigen Datentypen und einige Validationsregeln. Dass dies visualisiert wird, ist natürlich eine gute Sache. Doch ich empfehle eine deutliche Unterscheidung von den Slices, z.B. durch räumliche Trennung oder andere Farben.)
Diese Systematik zu sehen, hat mich schon begeistert. Doch das Team zeigte mir noch mehr. Es setzt nämlich auch meine Empfehlung um, einzelne Features dem Product Owner über einen Prüfstand zum Feedback vorzulegen.
Hier der Prüfstand für den Cluster von Features, den ich an der Wand hervorgehoben habe:
Der Product Owner (oder auch ein Tester) kann mit dem Prüfstand wie mit einer speziellen Messsonde gezielt einen kleinen Teil des Gesamtverhaltens prüfen, ohne die ganze Anwendung oder auch nur den ganzen Dialog zu bemühen.
Das macht erstens das Feedback einfacher. Zweitens wird der Product Owner damit frei, sich Features in quasi jeder beliebigen Reihenfolge zu wünschen. Und drittens können Features, Interaktionen, Dialoge nun viel einfacher parallel entwickelt werden.
Voraussetzung für den Prüfstand ist, dass Inkrement-Wünschen des Product Owners sehr konkrete Artefakte der Programmierung zugeordnet sind. Genau das leistet die inkrementelle Dekomposition mit der Herstellung von Slices jedoch.
Das Fazit von Entwicklern wie Testern sowie Product Owner bisher: die Softwareproduktion ist viel flüssiger geworden.
Darüber freue ich mich sehr! Und ich bin überrascht. Denn so eine pragmatische und zügige Umsetzung des in der CCD School vorgestellten Ansatzes hatte ich bisher noch nicht gesehen. Hier zeigt ein Team, was möglich ist, wenn man echt etwas verändern will. Die Initiative zweier motivierter Entwickler reichte aus, die anderen Teammitglieder waren offen für eine Veränderung und die Führungsebene darüber hat den Freiraum zu solcher Selbstorganisation gegeben.
Drei notwendige Faktoren sind bei diesem Kunden also glücklich zusammengekommen. Super!
Mehr Fluss, mehr Produktivität sind möglich mit systematischerer Softwareproduktion. Das so deutlich zu sehen, spornt mich an, nicht nachzulassen bei der Vermittlung von und Suche nach besseren Methoden.