Als vor über zwei Jahrzehnten das Extreme Programming mit seinen Ideen und Programmierpraktiken aufkam, war das Pair-Programming revolutionär – zwei Entwickler arbeiten zusammen an einer Aufgabe, die sonst ein Entwickler alleine gelöst hat. "Endlich Zusammenarbeit!", jubelten die einen. "Was für eine Verschwendung", fluchten die anderen. Und zwar nicht nur die Manager, die gerne auf Effizienz und Optimierungen achten, sondern auch Entwickler, die vielleicht lieber alleine arbeiten. Mit der Zeit entwickelten sich die Programmierpraktiken weiter, und seit einigen Jahren wird nun das Team-Programming (auch bekannt als Mob-Programming oder Ensemble-Programming) propagiert, bei dem das ganze Team zusammen eine Aufgabe löst.
Das mag verrückt klingen, funktioniert aber erstaunlich gut - und bügelt ein paar Schwachstellen aus, die viele Entwickler beim Pair-Programming empfinden. Zudem ergeben sich einige positive Wirkungen fast nebenbei, die man sonst mühsam zu erreichen versucht. Sei es, dass eine Gruppe von Entwicklern überhaupt als Team zusammenfindet, sei es, dass das Team lernt, Konflikte konstruktiv auszutragen und gemeinsame Konventionen zu entwickeln. Dabei gibt es kein Richtig oder Falsch. Beim Team-Programming geht es vor allem darum, dass das Team besser zusammenarbeitet, was auch immer das für das jeweilige Team bedeutet. Das ist absolut wichtig, aber es haben sich ein paar Tipps herauskristallisiert, wie man an das Team-Programming herangehen sollte, damit es sich möglichst bald gut anfühlt (was wichtig für die Akzeptanz ist) und damit man es mit Mehrwert einsetzen lernt. Anschließend kann man dann mit dem Team-Programming experimentieren und es Schritt für Schritt für das aktuelle Team anpassen.
Ein bisschen Geschichte
1999 beschrieb Kent Beck die Werte, Prinzipien und Praktiken des Extreme Programming, darunter Pair-Programming. Spätestens 2003 kam die Idee auf, Pair-Programming mit mehr als zwei Entwicklern durchzuführen. Allerdings fand dieser Ansatz kaum Beachtung – vielleicht auch, weil schon die Vorstellung, zwei Entwickler mit einer gemeinsamen Aufgabe zu betreuen, noch zu neu war. Vielleicht auch, weil das Vorgehen dieser Zusammenarbeit noch nicht so gut beschrieben war, dass sich daraus ein Mehrwert erkennen bzw. erleben ließ.
2011 überlegte Woody Zuill mit seinem Team bei Hunter Industries, wie sich ein Projekt, das zuvor unterbrochen worden war, neu aufsetzen ließe. Aufbauend auf TDD, Coding-Dojos und Pair-Programming lernten sie, konsequent, intensiv und direkt zusammenzuarbeiten und sich ständig in kleinen Schritten zu verbessern. Ganz nebenbei entstand so das, was das Team "Mob Programming" nannte. Nachdem Woody Zuill 2014 "Mob Programming – A Whole Team Approach" auf einer Konferenz vorgestellt hatte (vgl. [Agil]), wurde es von immer mehr Teams und Firmen eingesetzt und angepasst, beispielsweise für Remote-Arbeit.
2016 bekam ich irgendwo im Netz von dieser neuen Idee mit. Und weil ich damals schon länger als Pair-Programming-Coach unterwegs war, suchte ich (erfolgreich!) nach einem Team, was dieses „Mob-Programming“ zusammen mit mir ausprobieren würde. Seitdem ist Mob- bzw. Team-Programming meine bevorzugte Art, Teams an echte Zusammenarbeit heranzuführen, weil es mit ein bisschen Moderation meiner Erfahrung nach leichter erlernt werden kann als Pair-Programming. Und auch das Pair-Programming profitiert oft von funktionierendem Team-Programming – letztlich ist ein Pair ja auch ein Team, wenn auch ein kleines.
Was ist Team-Programming?
Die Idee vom Team-Programming ist, dass alle, die wir zur Umsetzung einer Aufgabe benötigen, gleichzeitig und gemeinsam daran arbeiten. Dadurch werden Wartezeiten auf Wissensträger:innen, Antwortgeber:innen, die Bearbeitung eines Pull-Requests usw. vermieden. Und anstatt viele verschiedene Aufgaben anzufangen, haben wir plötzlich die Möglichkeit, die wichtigste (höchstpriorisierte) Aufgabe zügig fertig zu bekommen. Woody Zuill nennt diese Art der Zusammenarbeit "all the brilliant people working on the same thing, at the same time, in the same space, and on the same computer" (all die großartigen Menschen arbeiten an derselben Sache, zur selben Zeit, im selben Raum und am selben Computer). Und man sieht bereits auf Abbildung 1, dass dabei nicht nur Entwickler beteiligt sind, sondern durchaus auch Product Owner (PO), Qualitätsspezialisten (QS) und andere Rollen. Der ursprüngliche Name "Mob" war wohl eher als Witz des Teams gedacht, das einen lustigen Namen für sich gesucht hatte. „Mob Programming“ wird aber leider häufig zu "Mobbing" abgekürzt, was nicht nur im Deutschen ein extrem negativer Begriff ist, sondern auch im Englischen (auch wenn es dort mit "harrassment" und "bullying" diverse andere Begriffe für Mobbing gibt). Weltweit wurde und wird daher nach besseren Namen gesucht. "Ensemble Programming" taucht derzeit häufiger auf. Woody Zuill nannte diese Zusammenarbeitspraktik schon recht früh "Whole Team Programming". Mittlerweile kürzt er dies zu "Team Programming" ab, weshalb ich hier diese Bezeichnung nutze. Aber der Name ist nur Schall und Rauch, es kommt auf andere Dinge an.
Abb. 1: Die Grundidee von Team-Programming – alle relevanten Personen arbeiten zur selben Zeit zusammen
Worauf es ankommt
Grundlegend ist die aktive Beteiligung aller Teilnehmer an der Team-Programming-Session, was nicht nur die Aufmerksamkeit, sondern auch die Kreativität fördert. Das stellen wir durch Folgendes sicher:
- Der Platz an der Tastatur wird regelmäßig gewechselt.
- An der Tastatur programmiert man nicht selber aktiv, sondern lässt sich vom Rest anleiten.
- Es sollten nicht zu wenige und vor allem nicht zu viele Teilnehmer sein.
- Das Team reflektiert regelmäßig über seine Arbeitsweise.
Warum ist das alles wichtig? Wer schon einmal in einem Pair saß, in dem einer die ganze Zeit redet, tippt und an der Tastatur "klammert", während der andere im Wesentlichen nur zuschauen darf, weiß, wie zäh und ermüdend der Versuch sein kann zusammenzuarbeiten. Und für die "Vortragende" ist es irgendwann auch frustrierend, weil man merkt, dass der andere nicht mehr bei der Sache ist. Hier funktionieren die beiden Rollen "Driver" und "Navigator" vom Pair-Programming vermutlich nicht gut, denn es fehlt Abwechslung und die echte Beteiligung beider Entwickler. Man nennt diese Variante, die man meiner Erfahrung nach leider erstaunlich häufig antrifft, das "Driver-Observer-Anti-Pattern" oder das "Worker/Watcher-Anti-Pattern" (siehe Abbildung 2). Kurzzeitig mag das helfen, weil es vielleicht schon eine Verbesserung des Miteinander darstellt.
Aber mittelfristig ist es oft Zeitverschwendung, weil das Vorgeführte am "Watcher" oft nur vorbeirauscht und nicht wirklich aufgenommen oder gelernt wird. Das heißt, ein regelmäßiger Tausch der Rollen zwischen den beteiligten Entwicklern, das Weitergeben der Tastatur, ist entscheidend – auch beim Team-Programming. Beim Team-Programming nutzen wir daher feste, kurze Zeitfenster (Timeboxes), nach denen der Platz an der Tastatur weitergegeben wird. Bei einer Session vor Ort startet man am besten mit 5 bis maximal 10 Minuten. Bei Remote-Sessions sind die Zeitfenster eher ein bisschen länger (10 bis 15 Minuten), weil das Weitergeben der virtuellen „Tastatur“ etwas länger dauert (dazu später mehr). Weil es sehr menschlich ist, dass man die Zeit vergisst – gerade bei so kurzen Zeitblöcken –, sollten wir uns per Timer an den Wechsel erinnern lassen. Dies funktioniert zudem prima als spielerische Ermahnung für diejenigen, die gerne länger als abgesprochen an der Tastatur festhalten wollen.
Abb. 2: Wenn der Navigator zum Zuschauer verkommt – das Driver-Observer-Anti-Pattern
Als Timer kann man vor Ort problemlos sein Smartphone nutzen. Hilfreich ist es allerdings, wenn der Timer für alle sichtbar ist. Dies schaffen Web-Timer, die man einfach im Browser auf einem separaten Bildschirm laufen lassen kann (siehe [Mobt] oder [Cuck]). Bei Remote-Sessions wird die URL des Web-Timers in den Session-Chat geschrieben, sodass jeder Teilnehmer den Timer auf dem eigenen Gerät laufen lassen kann.
5 oder 10 Minuten Zeitfenster klingen vielleicht lächerlich kurz. Wer jetzt denkt: „In der kurzen Zeit schaffe ich doch gar nichts an der Tastatur ...“ – hat recht! Denn darauf kommt es gar nicht an, und das ist ein weiterer wichtiger Punkt für gelungenes Team-Programming. Die meisten von uns sind darauf konditioniert, möglichst schnell viel Code zu tippen. Das Problem dabei: Für außenstehende Beobachter ist dies oft zu schnell, um den Code vernünftig zu verstehen. Einen solchen Driver kann man schlecht navigieren, weil man Probleme hat, den schnellen Eingaben und Sprüngen zwischen Dateien und Fenstern zu folgen.
Vor einigen Jahren hat Llewellyn Falco daher die "Strong Style Navigation" beschrieben, ursprünglich noch für Pair-Programming: Jede Idee muss, um zu Code zu werden, durch fremde Hände gehen. Wenn ich eine Idee habe, tippe ich also nicht mehr selber. Sondern wenn ich eine Idee habe, nimmst du die Tastatur und ich erkläre dir meine Idee so gut, dass du sie tippen kannst. Abbildung 3 zeigt den Unterschied.
Abb. 3: Klassische Navigation (aktiver Driver) vs. "Strong-Style"-Navigation (Ideengeber tippt nicht selber, sondern leitet an)
Die Person an der Tastatur wird also nicht selbst aktiv, sondern lässt sich vom Rest anleiten. Das wird zu Anfang oft noch sehr grundlegend sein, manchmal geht es um einzelne Zeichen oder Tastaturkürzel. Bald, wenn das Team schon etwas länger zusammengearbeitet hat, wird diese Navigation auf einem höheren, abstrakteren Niveau durchgeführt. Dies nimmt etwas Geschwindigkeit aus dem Coding, genauer: Die Geschwindigkeit wird an die Zuschauenden bzw. Lernenden angepasst, die plötzlich zu den Steuernden werden. Aus Gehetze wird so mit etwas Übung ein zügiger Marsch des gesamten Teams.
Die Rolle des Drivers nennt man beim "Strong Style" daher auch gerne "Typist" (Protokollant), der die Ideen des Teams in Code tippt. Programmiert bzw. entwickelt wird die Software dabei letztlich von den Navigatoren, also den übrigen, nicht-tippenden Teilnehmern. "Strong Style Navigation" ist der Standard beim Team-Programming. Gerade am Anfang sollte man das sehr ernst nehmen – und auch später nur aus gutem Grund davon abweichen. Ein typisches Team-Programming-Setup für ein so zusammenarbeitendes Team zeigt Abbildung 4.
Letztlich entscheidet auch die Anzahl der Teilnehmer darüber, wie gut die Session abläuft. Als ideal hat sich eine Größe von 4 bis 6 Teilnehmern gezeigt. Darunter tendiert die kleine Gruppe zu sehr zum "Groupthink" (Gruppendenken), das heißt, man trifft tendenziell schlechtere Entscheidungen, weil eine abweichende Meinung zu schnell untergeht. Bei mehr als sechs Teilnehmern wird es schnell zäh. Als Faustregel habe ich bei vielen Teams erlebt, dass vor Ort jeder Teilnehmer mindestens einmal pro halbe Stunde an der Tastatur sein sollte, remote mindestens einmal pro Stunde. Team-Programming wird also nicht immer vom gesamten Team durchgeführt, vor allem nicht bei großen Teams. Teilnehmerzahlen ab 8 verlieren schnell die Interaktion und die Beteiligung aller. Ich durfte auch schon Sessions mit 10 und mehr Teilnehmern begleiten. Das ist vor Ort leichter als remote.
So oder so sollten die Sessions dann aber nicht zu lang sein, weil vermutlich nicht alle Teilnehmer an die Tastatur kommen werden. Eine so große Session eignet sich zum Beispiel als Ersatz für eine 1h-Präsentation – aber nicht als reine Vorführung, sondern mit Interaktion.
Abb. 4: Typisches Setup einer Team-Programming-Session vor Ort
Mit der idealen Teilnehmerzahl von 4 bis 6 dauert eine Team-Programming-Session meistens zwei Stunden oder mehr, damit sich die Rüstzeit lohnt (Zurechtfinden in der Aufgabe, Zusammenfinden der aktuellen Teilnehmer:innen usw.). Wenn die Aufgabe allen klar ist oder die meisten schon daran gearbeitet haben, kann man auch eine Stunde effektiv zusammen nutzen. Ansonsten wird das Team oft von sich aus länger zusammen programmieren wollen (einen halben oder ganzen Tag).
Am Ende einer Session (bzw. eines Tages) führt das Team eine "Mini-Retro" durch, um die Arbeitsweise Schritt für Schritt jeden Tag ein bisschen zu verbessern. So werden Probleme schnell erkannt und aus dem Weg geräumt, bevor sie Frust erzeugen. Und vor allem kann das Team die guten Dinge erkennen und stärken. Dafür sammeln wir in einer Mini-Retro das, was heute gut war und was wir in der nächsten Session anders oder neu ausprobieren wollen. Es gibt dafür kein festes Format, vielleicht wird die Retrospektive auch nur mündlich durchgeführt.
Typische Fragen für ein Flipchart bzw. ein Online-Board zeigt Abbildung 5. Kurz bedeutet, dass die Mini-Retro in der Regel 5 bis maximal 15 Minuten dauert. Manchmal wird es aus gutem Grund länger dauern, manchmal ist vielleicht gar keine Retro erforderlich. Aber gerade am Anfang sollte man darauf achten, dass das Team regelmäßig darüber nachdenkt, was es an der eigenen Arbeitsweise stärken und was es anpassen möchte (z. B. die Timebox-Länge, die Werkzeuge, das Mobiliar bzw. den Raum o. Ä.).
Abb. 5: Mögliche Vorlagen für Mini-Retros, am Flipchart vor Ort oder auf einem Online-Whiteboard
Wenn niemand weiter weiß
Am besten ist es, wenn das Team für die ersten Team-Programming-Sessions Aufgaben auswählt, bei denen mindestens einer oder zwei aus dem Team wissen, wie man die Aufgabe löst, und somit die anderen anleiten können. Es fühlt sich gut an, wenn man nicht ständig alle Grundlagen in der Suchmaschine erfragen muss – der Einstieg ist deutlich leichter.
Aber auch für später ist dies wichtig: Wenn niemand im Team die Kompetenzen hat, um die anstehende Aufgabe umzusetzen, laden wir die nötigen Kolleginnen und Kollegen aus anderen Teams zu unserer Team-Programming-Session ein. Wenn wir solche Kollegen nicht finden, könnten einige wenige (zur Not nur einer) aus unserem Team mit einem Prototyp bzw. Spike die neue Technologie bzw. die Umsetzbarkeit der Aufgabe damit erforschen. In der Team-Programming-Session wird dann aber nicht einfach der fertige Prototyp vorgestellt bzw. der Code davon übernommen. Stattdessen beginnt das Team wieder ganz von vorne, aber mit dem Wissen aus dem Prototyp. Das heißt, das Team kann unter Anleitung die grundlegenden, wichtigen Schritte selber erfahren.
Wenn man merkt, dass niemand mehr weiter weiß und dass eine gemeinsame Recherche nicht in gefühlt akzeptabler Zeit die nächsten möglichen Schritte aufzeigt, sollte man aufhören und die Team-Programming-Session vertagen. In der Zwischenzeit kann jeder für sich ein bisschen recherchieren. Aber Achtung: Recherchieren heißt nicht fertig programmieren! Das heißt, es hilft dem Team nichts, wenn jemand in der folgenden Session eine fertige Lösung präsentiert. Hinter dieser Einzellösung steht das Team dann im Zweifel nicht. Es ist vollkommen in Ordnung, mögliche Lösungsideen für sich alleine auszuprobieren und die Aufgabe vielleicht sogar zu lösen.
Am Anfang der nächsten Team-Programming-Session teilt man diesen Erfolg dem Team mit – und leitet das Team dann an, das nochmal ganz bei Null startet. Das wird vielleicht nicht die „perfekte“ selbstgebastelte Lösung liefern. Aber das Team versteht die ersten, grundlegenden Schritte und kann bei der weiteren Umsetzung deutlich fundierter mitdiskutieren und mitarbeiten. Nach dem Erleben der grundlegenden Schritte könnte sich das Team auch einfach die vollständigere Lösung gemeinsam anschauen, besser verstehen als zuvor – und im Zweifel dann doch übernehmen, nur jetzt mit der nötigen Überzeugung.
Worauf sollten wir noch achten?
Am Anfang jeder Team-Programming-Session ist es absolut sinnvoll, dass sich alle Teilnehmer Klarheit über die anstehende Aufgabe verschaffen. Wir gehen die Aufgabe (z. B. in Form einer User-Story) gemeinsam durch, diskutieren, ob die Akzeptanzkriterien verständlich sind – und planen dann den bzw. die ersten Schritt(e). Vor allem setzen wir uns ein gemeinsames Ziel für diese Session. Das kann beispielsweise sein, dass wir das Setup auf allen Teilnehmer-Rechnern passend für die Aufgabe erweitern. Oder dass wir uns bewusst nur den ersten Schritt (und nicht auch den zweiten oder dritten) vornehmen, um schädlichen Stress zu vermeiden. Diese Abstimmung bzw. Planung sollte nur wenige Minuten dauern, idealerweise maximal ein oder zwei Zeitrahmen. Denn im Verlauf des Team-Programmings ändern sich die Ziele ziemlich sicher – wir müssen nur daran denken, sie immer wieder gemeinsam mit allen neu abzustimmen.
So eine Neujustierung der (Zwischen-) Ziele kann prima rund um die Pausen stattfinden. Bevor wir in eine Pause gehen, fragen wir: Wo stehen wir? Und vor allem: Was ist der nächste konkrete Schritt? Nach der Pause lohnt es sich, nochmal mit "Was ist nun der nächste, kleine Schritt?" zu starten. Wenn das jemand anderes als vor der Pause beantwortet, merkt das Team auch gleich, ob alle ein ähnliches Verständnis der Aufgabe haben. Pausen machen wir meistens einmal pro Stunde, zum Beispiel für 10 Minuten. Aber damit kann und sollte das Team experimentieren, denn die Notwendigkeit und Dauer von Pausen wechselt mit der Aufgabe, der Anzahl der Teilnehmer, der Remote- bzw. Vor-Ort-Situation usw.
Wichtig ist nur, dass man die regelmäßigen, kurzen Pausen nicht vergisst – was beim Coden leicht passiert. Die Mittagspause sollte nicht die einzige Unterbrechung des Arbeitstages sein, wenn man so intensiv zusammenarbeitet! Eine Pause ist sinnvoll, bevor die Aufmerksamkeit zu sehr nachlässt. Nötigenfalls lassen wir uns per Timer daran erinnern. Alternativ kann man eine ganz andere Möglichkeit für Pausen eröffnen – mit „dynamischem“ Team-Programming. Wer nicht gerade an der Tastatur sitzt und nicht den aktivsten Part der Diskussion trägt, kann jederzeit die Team-Session für eine Pause verlassen. Es sind ja noch genügend weitere Kollegen anwesend, welche den Typisten navigieren können. Und das klappt nicht nur bei Pausen, sondern auch mit längeren Terminen, die ein einzelner wahrnehmen muss (Meetings usw.). Nach dem Termin kehrt man zur Team-Session zurück, schaut den Rest des laufenden Zeitrahmens zu – und wird danach Typist und lässt sich anleiten. So steigt man schnell wieder in die Team-Session ein, ohne zu viel zu fragen und ohne dass die Kollegen alles nochmal erklären müssen.
Man kann Team-Programming für alle Aufgaben, das heißt zu 100 Prozent machen. Es gibt weltweit Teams, die dies mit Erfolg einsetzen. Aber das ist gar nicht nötig. Die positiven Effekte von Team-Programming zeigen sich schon, wenn man auch nur wenige Male pro Woche als Team zusammen entwickelt. Viel wichtiger ist das gemeinsame Starten! Wenn die Umsetzung einer Aufgabe beginnt, werden oft die Grundlagen des Designs, der Konfiguration usw. gelegt – und es tauchen oft die spannendsten Entscheidungen auf. Wenn das Team diese Grundlagen gemeinsam aufbaut, ist es viel leichter, sich dann bei Bedarf aufzuteilen – in mehrere kleine Team-Sessions, Pairs oder als einzelne Entwickler. Wenn das gesamte Team später wieder zusammenkommt, sind die Entwicklungen, die zwischendrin passiert sind, viel leichter zu verstehen – weil alle den Anfang mitbekommen haben (siehe Abbildung 6).
Abb. 6: Zusammen zu starten ermöglicht sinnvolleres Aufteilen der Aufgabe und später das leichtere Zusammenbringen der Ergebnisse
Manchmal ist es schwierig, auf die eigentliche Aufgabe fokussiert zu bleiben, wenn alle Teilnehmer plötzlich viele kleine, gute Ideen einbringen. Um sich nicht zu verzetteln und unsere Köpfe freizubekommen ("wenn wir das jetzt nicht machen, vergessen wir das"), schreiben wir unsere vielen Ideen gerne auf. Erstmal sehr unstrukturiert, nach und nach entwickelt sich eine Struktur (z. B. nächste Schritte, in dieser Aufgabe nicht vergessen, Ideen für andere Storys usw.) und eine Priorisierung. Wichtig ist, dass wir den nächsten konkreten Schritt, den wir umsetzen wollen, für alle sichtbar hingeschrieben haben. Manchmal machen wir das mit Zetteln auf einem (Online-)Whiteboard. In letzter Zeit nutzen wir zunehmend einfach eine TODO-Textdatei, die auf oberster Ebene des Projekts mit eingecheckt und bei Beendigung der Aufgabe aufgeräumt und gelöscht wird. Damit merken wir uns alle Ideen strukturiert, aber formlos, und vermeiden somit unnötige Bürokratie, die durch das Anlegen von Unteraufgaben im Ticketsystem entstünde.
Wenn das Team gelernt hat, in der Strong-Style-Navigation zu arbeiten, das heißt, dass sich der Typist von den anderen Session-Teilnehmern leiten lässt, ermöglicht es diese Arbeitsweise dann auch, den PO, einen UX-Kollegen oder die Teamleitung dazuzunehmen. Das klingt und ist erst einmal ungewohnt, kann aber eine tolle Dynamik in die Session bringen. Wenn die Entwickler das zu lösende Problem jemandem erklären, von dem sie denken, dass er oder sie nicht programmieren kann, habe ich mehr als einmal erlebt, dass die Entwickler sich gegenseitig plötzlich tolle Einblicke und Hintergrundinformationen gegeben haben, die zuvor als selbstverständlich angenommen worden waren. Am besten startet man aber zunächst mit den Entwicklern und übt den Ablauf, vor allem, wenn die Aufgaben eher Codinglastig sind. Wenn das halbwegs rund läuft, kann das Team problemlos ein oder zwei Wenig- oder Nicht-Coder dazunehmen. Die Nicht-Programmierer sollten bei Coding-Aufgaben aber besser in der Minderheit sein – oder das Team gibt der Session bewusst einen anderen Schwerpunkt bzw. ein anderes Ziel.
Warum funktioniert das?
Durch Team-Programming kann ich anderen beim Denken und Machen zuschauen. Das implizite Wissen und Können wird explizit gemacht. Als Typist kann ich es selber unter Anleitung ausprobieren. Und dann kann ich versuchen, andere anzuleiten – es sind ja genügend Kollegen in der Session dabei, die mein Anleiten verbessern können. So entsteht eigenes Wissen und vor allem Können.
Das ist erst mal ungewohnt und löst oft Ängste aus: "Ich muss an die Tastatur, während alle mir zuschauen." Wenn man aber nochmal verdeutlicht, dass die Tastatur auch schnell wieder beim nächsten Typisten ist, trauen sich dann doch die meisten mitzumachen. Und im Netz finden sich diverse Berichte, dass gerade dieses ungewohnte Format auch für eher introvertierte Entwickler nach einer Eingewöhnung sehr bereichernd ist.
Denn es hat sich gezeigt, dass ein Team, wenn es in so einer sachbezogenen Runde – nötigenfalls unter Anleitung – respektvoll und sachlich zu diskutieren lernt, einen Raum der (psychologischen bzw. emotionalen) Sicherheit schaffen kann – einen geschützten Raum, in dem es in Ordnung ist, eine vermeintlich "dumme" Frage zu stellen. Weil das Team plötzlich merkt, dass mehr als einer diese Frage hat. Ich stehe mit meinem Problem nicht allein da. Andere springen mir bei – oder verstehen mich besser und können mein Anliegen dem Rest erklären, wenn ich das selber nicht schaffe. Kritische Situationen durch Missverständnisse und ungewollt persönlich empfundene Aussagen werden so durch den Rest vom Team entschärft.
Ich traue mich zu fragen, weil ich merke, dass einige meiner Fragen selbst von den "Profis" im Team nicht so ohne weiteres beantwortet werden können. Und weil ich erlebe, dass auch die vermeintlichen Rockstar-Entwickler nach Dingen fragen, die ich kenne und die ich ganz einfach finde – bei denen ich also aushelfen kann. Das gemeinsame Machen mit allen kleinen Fragen und Problemen ist der essenzielle Unterschied zu einem "Show & Tell"-Format, der wichtige Unterschied zum nur zusammensitzen und reden. Das Team löst nicht nur die Aufgabe gemeinsam, es hilft sich gegenseitig bei (Setup-) Problemen, zeigt IDE-Tastaturkürzel, hilfreiche Suchbegriffe für die Internet-Suchmaschine, fachliche Besonderheiten, die so nicht im Unternehmens-Wiki stehen. Dadurch wird nicht nur implizites Wissen weitergegeben, sondern auch viel Können – also das, was einen guten Entwickler ausmacht. Und gerade beim impliziten Wissen tun wir uns sonst oft schwer, dies angemessen zu dokumentieren: So, dass es nicht veraltet, so, dass es gelesen wird. Hier ist es meist viel einfacher, jemandem zuzuschauen, Fragen zu stellen und es selber auszuprobieren.
Weil jeder im Team mal tippt, mal mitdiskutiert, entsteht der Code wirklich gemeinsam. Es geht nicht mehr um "meinen Code" und "deinen Code". Dieses „Co-Authoring“ oder "Co-Creating" ist eine sehr starke Art der Kollaboration.
Dafür muss das Team oft die neuen Rollen lernen (Typist:in als „Protokollant:in). Einige müssen lernen, Geduld zu haben, respektvoll auf Missverständnisse und Fehler hinzuweisen. Andere müssen lernen, den Mut zu haben, sich einzubringen, auch mal Neues auszuprobieren. Aber wenn ein Team dies konsequent und anfangs mit der nötigen Geduld übt, werden die Kollegen sehr schnell bessere Sparringspartner für die gemeinsame Entwicklung, egal ob mit Team-Programming oder bei Einzelaufgaben. Und für "Rockstar-Entwickler", die eher ungeduldig und oft genervt davon sind, dass sie alles dreimal erzählen müssen, hat Team-Programming den angenehmen Nebeneffekt, dass man es nur einmal in der Team-Session erzählen muss. Häufig ist ein Kollege dabei, der es sofort versteht und das Team nun beim zweiten Mal anleiten kann.
Es steckt noch sehr viel mehr im Team-Programming, was Stoff genug für einen eigenen Artikel ist: Durch die regelmäßige intensive (und anfangs idealerweise moderierte) Zusammenarbeit mit wechselnden Team-Session-Teilnehmern lernt das Team, Konflikte zügig, vertrauensvoll und konstruktiv zu lösen. Man kann beobachten, dass die Phasen des Teambuildings häufiger, dafür zunehmend weniger kritisch durchlaufen werden. Und ganz nebenbei lösen sich diverse Dysfunktionen, die man in Gruppen antrifft, durch das Erleben der Zusammenarbeit auf. Nebenbei passt diese Arbeitsweise wunderbar zu IT-Kanban mit einer Limitierung des "Work in Progress" (WIP). Beim Team-Programming haben wir implizit ein sehr geringes WIP-Limit – bei einem kleinen Team, das sämtliche Aufgaben mit Team-Programming durchführt, haben wir sogar ein WIP-Limit von 1, das heißt, die eine aktuelle Aufgabe wird erst fertig gestellt, bevor sich das Team die nächste Aufgabe nimmt. Dieser Fokus bringt mehr Ruhe ins Team und dadurch hoffentlich bessere Ergebnisse für unsere Kunden.
Remote - das neue Normal
Auch wenn bisher im Text schon ab und zu von Besonderheiten beim Remote-Team-Programming die Rede war, gibt es dabei eine besondere Schwierigkeit: Wie geben wir die "Tastatur" (den aktuellen Arbeitsstand) weiter? Denn wenn das Zeitfenster vom derzeitigen Typisten abgelaufen ist, compiliert der Code-Stand vielleicht noch gar nicht. Oder die Tests sind nicht (mehr) grün. Oder die Aufgabe ist noch nicht fachlich korrekt gelöst. Vor Ort macht das nichts. Es geht einfach der Nächste an die Tastatur am selben Rechner und das Team setzt die Arbeit nahtlos fort. Committed bzw. gepusht wird der Code erst, wenn das Team den für sich üblichen Abschluss gefunden hat. Die Idee eines zentralen, gemeinsam genutzten Rechners kann man auch für die Remote-Situation umsetzen. Auf diesem Rechner wird die gemeinsam genutzte IDE konfiguriert und jeder Typist verbindet sich per Remote-Session auf diesen Rechner – der vielleicht nur virtuell in der Cloud existiert.
Alternativ nutzt man eines der zahlreichen IDE-Plug-ins, mit denen die IDE eines Entwicklers für alle Teilnehmer der Team-Programming-Session freigegeben wird. Alle Teilnehmer arbeiten remote auf dem freigebenden Rechner, von dem aus der Code am Ende committed wird. Beispiele für solche Plugins sind "Code With Me" (IntelliJ), "Live Share" (Visual Studio Code) oder "Code Together" (neben den beiden genannten IDEs auch für Eclipse und im Browser verfügbar).
Vorteil ist, dass man bei diesen Varianten schnell einsteigen kann – man benötigt nur einen Remote-Session-Client oder eine passende IDE mit Plug-in, schon kann man auf dem passend konfigurierten Rechner mitcoden. Setup- bzw. Infrastrukturprobleme, die gerade am Anfang viel Zeit kosten, blendet man damit aus. Das ist aber auch der größte Nachteil: Wenn man nicht aufpasst, dass die IDE in jeder Folgesession von einem anderen Teilnehmer freigegeben wird, ist das Team schnell von dem einen Rechner abhängig, auf dem alles läuft. Außerdem gibt es bei den Remote-Client-Sessions bzw. IDE-Freigaben häufiger Latenzprobleme bei Tastatureingaben, zum Beispiel bei der Code-Completion. Und sobald man ein anderes Tool außerhalb der IDE verwendet, muss man doch wieder auf Screen-Sharing zurückgreifen.
Eine einfache und doch elegante Lösung ist das "mob"-Tool (siehe [Mob]). Damit arbeitet jeder Typist lokal und ohne Latenzen auf seinem komplett eingerichteten System. Die IDEs und übrigen Tools können gleich sein, müssen das aber nicht; dies ist Team-Entscheidung. Der Arbeitsstand wird über ein Git-Remote-Repository ausgetauscht.
Das mob-Tool fasst die nötigen Git-Kommandos zu wenigen Befehlen zusammen, mit denen die Team-Programming-Session durchgeführt wird – im Wesentlichen „mob start“, "mob next“ und „mob done“. Das Tool legt am Anfang automatisch einen temporären Git-Remote-Branch an, auf den es die lokalen Änderungen des aktuellen Typisten am Ende des Zeitfensters pusht. Der nächste Typist pullt den – eventuell gar nicht lauffähigen – Arbeitsstand von dort usw. Erst am Ende der Team-Programming-Session werden die vielen kleinen Commits aus dem temporären Branch zu einem einzigen Commit auf dem Basis-Branch konsolidiert („gesquasht“) und der temporäre Branch automatisch vom mob-Tool gelöscht. Abbildung 7 verdeutlicht den Ablauf. Der jeweilige Typist teilt dabei seinen Bildschirm. Alle anderen Teilnehmer haben idealerweise die Kamera eingeschaltet, damit das Team auch Mimik und Gestik zur Kommunikation nutzen kann – wie bei einer Team-Programming-Session vor Ort.
Diese Form von Team-Programming für verteilte Teams wurde bereits lange vor der Corona-Pandemie von einem Team als „Remote Mob Programming“ entwickelt und auf der Webseite [Remo] bzw. in dem Buch [Chr19] beschrieben. Beides ist lesenswert, denn dort finden sich unabhängig vom Team-Programming gute Ideen zur Remote-Arbeit. Wer sich mit dem „Remote Manifest“ von GitLab beschäftigt, wird einen wichtigen Unterschied feststellen. Das Remote Manifest betrachtet asynchrone Kommunikation wichtiger als synchrone, Niedergeschriebenes wichtiger als begleitetes Erleben (siehe [Gitl]). Remote-Team-Programming dreht genau das um. Wie beim Team-Programming vor Ort haben wir eher synchrone Kommunikation, eher gemeinsames Machen und Erleben, weniger Wartezeiten, weniger implizites Können. Dies ist ein anderer Kompromiss – denn während das Remote Manifest u. a. darauf abzielt, Mitarbeiter eines Teams über die ganze Welt verteilt arbeiten zu lassen, geht synchrone Arbeit natürlich nur, wenn das verteilte Team in ähnlichen Zeitzonen arbeitet.
Wie immer geht es dabei nicht um ein Entweder-oder, sondern um den Schwerpunkt bzw. die bevorzugte Arbeitsweise. Eines der Teams, die ich zuletzt coachen durfte, war über Deutschland und Indien verteilt. Sie haben für sich den Kompromiss gefunden, an drei Tagen in der Woche jeweils zwei Stunden Remote-Team-Programming zu machen. Gegen Ende des Arbeitstages in Indien finden sich zwei überlappende Stunden mit dem Arbeitstag in Deutschland. Nach der gemeinsamen Team-Programming-Session machen die Kollegen in Deutschland weiter und pflegen die TODO-Datei im Projekt (s. o.), damit die Kollegen in Indien am anderen Morgen an der passenden Stelle weitermachen können (vgl. [Link]).
Abb. 7: Schematischer Ablauf der mob-Tool-Verwendung in einer Remote-Team-Programming-Session
Und künftig hybrid?
Derzeit ist Remote-Arbeit im Homeoffice gerade im IT-Bereich oft zu 100 Prozent erlaubt und gewünscht. Aber auch nach der Pandemie werden wir vermutlich bzw. hoffentlich nicht zu 100 Prozent ins Büro zurückkehren. Firmen und Mitarbeiter haben in den letzten Monaten unerwartet viele Vorteile durch die Remote-Arbeit für sich entdeckt. Spannend wird dann die Hybrid-Arbeit, das heißt, wenn ein Team teilweise zu Hause, teilweise im Büro arbeitet, und das an verschiedenen Wochentagen noch mit unterschiedlicher Besetzung.
Wenn während einer Team-Programming-Session ein Teil des Teams im Homeoffice arbeitet und ein anderer Teil im Büro gemeinsam an einem Rechner in einem Meeting-Raum sitzt, wird es schwierig, alle zu integrieren – vermutlich werden zwei Gruppen entstehen, die jeweils untereinander diskutieren. Und vermutlich werden die Remote-Kollegen abgehängt, weil sie die Gespräche vor Ort nicht mitbekommen. Eventuell wäre es dann sinnvoller, zwei separate Team-Programming-Sessions zu verschiedenen Themen abzuhalten.
Für wirkliche Zusammenarbeit scheint derzeit der Grundsatz „eine:r remote – alle remote“ zu gelten, damit wir asymmetrische Information vermeiden. Bereits vor der Pandemie durfte ich solche Sessions begleiten. In diesem Fall haben sich die Kollegen vor Ort entweder an ihren Büroplätzen mit Headset und Rechner am Screensharing beteiligt. Oder aber sie haben sich in einem Raum versammelt, jeder mit eigenem Rechner (für die Kamera und das Screensharing), dann aber bevorzugt mit gutem Raummikro und gutem Lautsprecher. Außerdem mussten wir daran denken, dass die Remote-Kollegen Klebezettel vor Ort nicht sehen können, das heißt, wir haben auch in dieser Situation ein Online-Whiteboard genutzt. Das klappt erstaunlich gut! Gerade auch, wenn Team-Programming nicht zu 100 Prozent, sondern vielleicht einmal am Tag oder ein paarmal in der Woche für zwei bis drei Stunden genutzt wird – eher wie ein anberaumtes Meeting, wenn auch mit anderem Ablauf.
Wie lernt mein Team das?
Ein Team kann sich Team-Programming selber beibringen, beispielsweise auf Grundlage von Artikeln wie diesem. Zumal man auch beim Team-Programming besser nicht in den Kategorien Richtig oder Falsch denken sollte. Wichtig ist, dass das Team regelmäßig über seine Arbeitsweise reflektiert und sich schrittweise verbessert. Es hat sich aber gezeigt, dass es für einen guten Start hilfreich ist, wenn man Team-Programming mit jemandem kennenlernt, der bereits erfolgreiches Team-Programming selber erlebt hat. Komische Momente, Ruckeln, Wartezeiten, gefühlte Konflikte usw. können so mit der vorhandenen Erfahrung besser einsortiert werden, was tatsächlichen Konflikten vorbeugt und das Team schneller zu einem Ablauf bringt, der sich gut anfühlt.
Hilfreich ist auch, wenn der Entwickler mit Team-Programming-Erfahrung nicht selber Teil des programmierenden Teams ist, sondern eher die Rolle eines Moderators einnimmt. So ein Moderator muss nicht zwingend von außerhalb des Unternehmens kommen, sollte aber dem Team und den fachlichen Aufgaben nicht zu nahe stehen. Der Moderator achtet beispielsweise auf die Kommunikation der Teilnehmer, auf die Einhaltung der Zeitfenster und unterstützt das Üben der Strong-Style-Arbeitsweise. Denn gerade das sich selber Zurücknehmen als Typist ist anfangs für viele Entwickler ungewohnt und schlägt zu schnell in aktives, selbstgesteuertes Programmieren um. Und der Moderator kann, weil er selber nicht mit der konkreten Lösung der Aufgabe befasst ist, leichter an die rechtzeitige Beendigung der aktuellen Session denken, um eine Mini-Retro durchzuführen – das geht im Eifer des Gefechts sonst zu leicht unter.
Nach einer teamabhängigen Anfangsphase können die Teams die Sessions natürlich auch alleine durchführen. Von Zeit zu Zeit kann eine Begleitung durch Außenstehende aber immer wieder wertvolle Beobachtungen liefern, mit denen sich das Team dann selber weiterentwickeln kann. Als Programmieraufgabe für die ersten Team-Programming-Sessions kann man eines der zahlreich im Netz vorhandenen Coding-Dojos verwenden. Mehr Spaß macht es aber meiner Erfahrung nach, wenn das Team eine echte Aufgabe aus dem eigenen Projekt bzw. Produkt umsetzen kann. Dann sollte sich das Team am besten eine Aufgabe suchen, die nicht zu klein ist – sonst ist sie zu schnell erledigt und wir können die Typist-Rotation nicht üben. Die Aufgabe sollte auch nicht zu groß sein, damit wir Fortschritt erleben können. Große Aufgaben brauchen oft noch viel Recherche, und gemeinsame Recherche ist gerade zu Anfang schwierig. Wie weiter oben schon beschrieben: Am besten wählt das Team eine Aufgabe, von der ein oder zwei aus dem Team schon wissen, worum es geht und wie man die Aufgabe üblicherweise löst. Programmieraufgaben sind besser geeignet als Konfiguration/Infrastruktur/Admin-Aufgaben. Das geht zwar auch alles, aber es ist damit anfangs schwerer, in die Typist-Rotation zu kommen. Alternativ übt man die Typist-Rotation mit gemeinsamer Dokumentation zum Beispiel im zentralen Wiki – was übrigens auch eine gute Übung für Nicht-Programmierer ist. Welche Formate sind zum Erlernen von Team-Programming geeignet? In den letzten Jahren habe ich entweder Tages-Workshops durchgeführt mit einem ca. einstündigen Kickoff zu den Grundlagen, zwei Team-Programming-Sessions von jeweils ca. 2 Stunden Dauer und einem Abschluss im Retro-Stil. Dies gab den Teams bereits einen guten Impuls für weitere, eigene Versuche. Oder aber ich durfte Teams ein, zwei oder idealerweise vier Wochen begleiten. Dadurch konnten wir die Team-Programming-Sessions nach und nach in den vorhandenen (Sprint-) Ablauf einbringen und die tatsächlichen Team-Aufgaben gemeinsam lösen. Was nach relativ viel Moderator- bzw. Coaching-Einsatz klingt, hat aber nachhaltig dazu geführt, dass die Teams das gemeinsame Programmieren als brauchbares Werkzeug erlebt haben und nun bei Bedarf bewusst einsetzen.
Es gibt diverse Bücher darüber, was Team-Programming ist, wie man das im eigenen Team verankert oder coacht (siehe [Bac21], [Pea18], [Zui21] und [Pyh21]). Die Erfinder des Mob-Programming veröffentlichen auf ihrem YouTube-Channel „Mob Mentality Show“ sehenswerte Beiträge, außerdem pflegen sie eine Liste von weiteren Ressourcen im Netz (siehe [Yout] bzw. [Trel]).
Fazit
Team-Programming habe ich in den letzten Jahren als große Bereicherung erlebt. Kaum ein Team konnte daraus nicht den einen oder anderen Nutzen ziehen – wenn sich das Team darauf eingelassen hatte, mal etwas Neues auszuprobieren. Am Ende einer Team-Programming-Session haben wir statt Endlosdiskussionen oft nicht nur lauffähigen Code, der uns in Richtung der Lösung der eigentlichen Aufgabe bringt. Häufig werden dabei auch viele kleine Missverständnisse und Unklarheiten beseitigt und dadurch ganz nebenbei, aber spürbar zum Teambuilding beigetragen. Wer nun Team-Programming im eigenen Team ausprobieren möchte, sollte immer daran denken: Dieser Artikel beschreibt zwar die Grundlagen, die viele Teams weltweit als hilfreich empfinden – aber jedes Team ist anders. Wenn man auf Basis dieser Grundlagen einmal erlebt hat, wie gut Team-Programming funktioniert, kann und sollte man damit experimentieren, um das, was dem Team hilft, zu behalten und zu stärken, und das, was als nicht so gut empfunden wird, anzupassen und vielleicht schon nach der nächsten Session neu zu bewerten.
Team-Programming ist eine relativ neue Programmierpraktik, bei der sich in den kommenden Jahren noch viel tun dürfte. Vor zwei Jahren konnte sich kaum jemand vorstellen, dass wir so intensiv remote zusammen programmieren würden. Und wer weiß, welche neuen Ideen uns in den kommenden Jahren beim hybriden Team-Programming große Fortschritte bringen. Eines aber eint all diese Ansätze von Team-Programming: Zusammen zur selben Zeit an einer gemeinsamen Aufgabe zu arbeiten. Und das ist für viele Teams ein großer Schritt nach vorne.
Weitere Informationen
[Agil] Agile Alliance, Mob Programming – A Whole Team Approach, siehe: agilealliance.org/resources/experience-reports/mob-programming-agile2014/
[Bac21] E. Bache, Technical Agile Coaching with the Samman method, Leanpub, 2021
[Chr19] J. Christ, S. Harrer, M. Huber, Remote Mob Programming – At home, but not alone, Leanpub, 2019
[Cuck] A productivity timer for remote teams, siehe: cuckoo.team
[Gitl] GitLab, Remote Manifesto, siehe: about.gitlab.com/company/culture/all-remote/
[Link] Arjun RC auf LinkedIn, Building Teams With Mob Programming In The New Normal, siehe: linkedin.com/pulse/building-teams-mob-programming-new-normal-arjun-rc-he-him-/
[Mob] Fast git handover with mob, siehe: mob.sh
[Mobt] A collaborative timer for your mob team, siehe: mobti.me
[Pea18] M. Pearl, Code with the Wisdom of the Crowd, Pragmatic Programmers, 2018
[Pyh21] M. Pyhäjärvi, Ensemble Programming Guidebook, 2021, Download von: ensembleprogramming.xyz
[Remo] Remote Mob Programming, siehe: remotemobprogramming.org
[Trel] Trello, Software Profession Resources, siehe: trello.com/b/1lfMkCOh/software-profession-resources
[Yout] YouTube, Mob Mentality Show, siehe: youtube.com/channel/UCgt1lVMrdwlZKBaerxxp2iQ
[Zui21] W. Zuill, K. Meadows, Mob Programming – A Whole Team Approach, Leanpub 2021