Softwareentwicklung ist ein bisschen wie Basketball
Anton Drukh
4. August 2016
0 Min. LesezeitHeute möchte ich mich auf das Ziel des Engineering-Teams konzentrieren, Ergebnisse zu liefern, und zeigen, was uns bei Snyk dabei hilft. In unserem Entwicklungszyklus setzen wir auf verschiedene Praktiken, die gut zusammenspielen und dafür sorgen, dass wir kontinuierlich liefern. Ich erläutere die Philosophie hinter unserem Ansatz und stelle unsere Continuous-Delivery-Praktiken vor.
Immer liefern
Liefern bedeutet, bei Ihren Nutzern etwas zu bewirken. Gute Engineering-Organisationen liefern kontinuierlich. Ob Sie es nun Bereitstellen, Veröffentlichen oder in Produktion bringen nennen – gemeint ist immer dasselbe. Coole Technologien, gute Prozesse und Teamarbeit, die Eigenverantwortung fördert, helfen dabei, dieses Ziel zu erreichen.
In größeren Organisationen ist es üblich, nur alle paar Monate ein Release auszuliefern. Das erinnert mich an Fußballspiele: Es fallen nur wenige Tore, während sich das Spiel die meiste Zeit auf dem Feld hin und her bewegt. In jeden Spielzug fließt viel Energie, aber nur wenige führen zum Erfolg.
Basketball ist ein guter Vergleich für Continuous Delivery: Sobald der Ball in den Händen Ihres Teams ist, haben Sie 24 Sekunden Zeit, um zu werfen und einen Treffer zu erzielen. Das wiederholt sich während des Spiels so oft, dass es zur Normalität wird. Sie zielen ständig auf den Korb und planen nur den nächsten Spielzug, der nicht zu lange dauern darf. Die Zeitvorgabe ist entscheidend und prägt das Spiel maßgeblich.
Liefert alles aus!
Wie wird das Ausliefern also zur Gewohnheit? Würde es wirklich funktionieren, wenn Sie heute ins Büro kämen und verkündeten: „Lassen Sie uns alles innerhalb von zwei Stunden ausliefern!“? Ich bezweifle es.
Die Philosophie lässt sich auf wenige Grundsätze reduzieren:
1. Hindernisse angehen – schwierige Aufgaben aufzuschieben, ist nie eine gute Idee. Das sorgt nur dafür, dass Sie später statt früher ausliefern. Verlagern Sie alles, was an einem Release schwierig ist, so früh wie möglich im Prozess nach vorn. Beim Basketball heißt das: Wenn Sie auf einen Verteidiger treffen, sollten Sie nicht erst zurücklaufen, um sich später um die Blockade zu kümmern.
2. Den Korb im Blick behalten – ein Feature ist nur das Mittel, um Ihren Nutzern mehr Nutzen zu bieten, nicht das Ziel. Verstehen Sie die Anforderungen und finden Sie für Ihr Feature das beste Verhältnis von Mehrwert zu Aufwand. Beim Basketball heißt das: Wenn Sie den Ball in den Händen halten, schauen Sie zum Korb und wählen Sie den direkten Weg.
3. Schnell scheitern – jedes Feature birgt Risiken: Versuchen Sie nicht, einen narrensicheren Plan zu entwickeln. Wenn etwas nicht funktionieren wird, sollten Sie das möglichst früh herausfinden und von vorn beginnen. Beim Basketball ist es besser, auf den Korb zu werfen und daneben zu treffen, als darauf zu warten, dass der Schiedsrichter nach 24 Sekunden abpfeift.
Gute Merges sind solche, die gar nicht nötig sind
Welche schwierigen Aufgaben beim Ausliefern werden noch schwieriger, wenn man sie nicht sofort angeht?
Ein solcher Knackpunkt ist das Zusammenführen Ihrer Änderungen mit denen anderer. Merges können die Hölle sein. Alles, worüber wir sprechen, wenn wir von „gemeinsamer Code-Verantwortung“ reden, ist vergessen, wenn ich auf zehn Dateien mit jeweils Dutzenden Konflikten schaue. Stellen Sie sich einen Basketballspieler vor, der über das Feld auf den Korb zuläuft. Plötzlich muss er den Ball beiseitelegen, eine Schaufel holen und einen Haufen … Erde durchgraben. Die Energie des Spiels verpufft. Wenn er das nächste Mal den Ball bekommt, hält er eher nach der Schaufel als nach dem Korb Ausschau.
Eine Möglichkeit, das zu vermeiden, ist eine strikte Aufgabenteilung, bei der während eines Sprints niemand am selben Code wie die anderen arbeitet. In einer kontrollierten Umgebung mag diese Methode funktionieren, aber so sieht unsere Arbeitsumgebung nicht aus. Eine solche strikte Aufteilung widerspricht der gemeinsamen Verantwortung und fördert Silos in der Softwareentwicklung. Das stärkt das Team nicht und bremst die persönliche Weiterentwicklung. Am besten vermeiden Sie das.
Unser Ansatz: kleinere Schritte. Denken Sie an das letzte große Merge voller Konflikte zurück, die Sie beheben mussten – wie lange hatten Sie vor diesem Merge schon programmiert? Wochen? Tage? Es sollte Sie nicht überraschen, dass sich der Code in dieser Zeit verändert hat – andere arbeiten parallel. Denken Sie schon an den nächsten Schritt, wenn Sie die erste Zeile Code für Ihr nächstes Feature schreiben. Behalten Sie den Korb im Blick, auf den Sie zielen: Wann bringen Sie Ihre Änderungen in den Feature-Branch ein? Oder besser noch: in die Produktion? Wenn die Antwort mehr als einen halben Arbeitstag lautet, überdenken Sie Ihren Plan. Sie wollen nicht hören, wie der Schiedsrichter nach 24 Sekunden abpfeift.
Mit Feature-Flags schneller vorankommen
Bei Snyk arbeiten wir mit persönlichen Branches, die innerhalb weniger Stunden erstellt, gepusht, geprüft, gemergt und bereitgestellt werden. Bei größeren Features, an denen wir über mehrere Tage hinweg schrittweise arbeiten, nutzen wir Feature-Flags, um sie im gleichen Tempo in die Produktion zu bringen – auch wenn sie noch nicht ganz ausgereift sind. Dahinter steht die Annahme, dass der Code selbst die beste Dokumentation ist und kein Architekturentwurf. Wenn Sie Ihre Pläne für sich behalten und in einem privaten Branch arbeiten, zielen Sie nicht nur nicht auf einen kurzen Sprint ab, sondern helfen auch den anderen nicht, schneller voranzukommen. Denken Sie an die 24 Sekunden.
Gute Tests sind frühe Tests
Ein weiterer Knackpunkt beim Release ist das Testen. Tests sind wichtig, doch der richtige Zeitpunkt macht einen großen Unterschied. Kurz vor dem Deployment festzustellen, dass etwas nicht so funktioniert wie gedacht, ist weitaus belastender, als dieselbe Erkenntnis wenige Minuten nach dem Schreiben von nicht ganz perfektem Code. Denken Sie an den ständigen Kontextwechsel: die Ursache des Bugs suchen, das Basketballspiel mitten im Spiel unterbrechen und so weiter. Keine gute Sache.
Auch wenn wir nicht strikt auf TDD setzen, hält uns eine umfassende Testsuite, die lokal und bei jedem Pull Request ausgeführt wird, in Form. Wir achten darauf, dass Tests einfach zu schreiben und schnell auszuführen sind. Das klingt einfach, erfordert aber viel Aufmerksamkeit und vor allem Eigenverantwortung. So ähnlich, wie man sich vor dem Spiel die Schuhe bindet: Wenn Sie wissen, dass es Ihnen hilft, Punkte zu erzielen, werden Sie sich die Mühe machen.
Zu den praktischen Maßnahmen: Wir ergänzen neue Features um Tests, besonders wenn wir hartnäckige Bugs beheben, die es bis in die Produktion geschafft haben. Unsere GitHub-Repositories sind in Travis CI integriert. Dort wird die Testsuite bei jedem Pull Request sowie nach Merges in die Branches develop und master ausgeführt. Ein erfolgreicher Testlauf in develop und master löst jeweils ein automatisches Deployment in unseren Dev- und Prod-Umgebungen aus und schließt damit unseren Continuous-Delivery-Zyklus ab. Über eine manuelle Opt-out-Option können wir ein Deployment nach einem Merge verhindern, indem wir einen geheimen String in die Commit-Nachricht aufnehmen. Ich bin sehr froh, dass es eine Opt-out- und keine Opt-in-Option ist. Ich weiß nicht mehr, wann wir sie zuletzt genutzt haben.
Teamwork ist entscheidend
Damit all das funktioniert, muss sich das Team darauf verständigen, schnell auszuliefern. Reibungslose Merges sind Teamarbeit – genau wie eine unterstützende Testsuite. Beides erfordert Zeit, Einsatz und Eigenverantwortung. Sprechen Sie im Team über die Knackpunkte im Release-Prozess und nehmen Sie schrittweise Änderungen vor. Bevorzugen Sie schnelle Erfolge gegenüber einer kompletten Überarbeitung.
Haben Sie einen besseren Vergleich als meinen mit Basketball? Möchten Sie Tipps teilen, die Ihr Team in Schwung bringen? Schreiben Sie uns auf Twitter.
Starten Sie mit Capture the Flag
Erfahren Sie in unserem virtuellen On-Demand-Workshop für Einsteiger, wie Sie Capture-the-Flag-Herausforderungen lösen.