Es gibt sie noch:
Die klassischen Enterprise-Projekte, die wie Öltanker auf hoher See unbeeindruckt von agilen Strömungen oder anbrandenden DevOp-Wellen ihren gewohnten Kurs halten. Im vorausgeplanten Takt produziert ein solches Projekt eine Handvoll Releases pro Jahr. Jedes einzelne Release wird in einem definierten Prozess von Stufe zu Stufe weitergereicht: Entwicklung, Test, Produktion.
In mehreren Projekten dieser Art trug der Autor (neben jeweils anderen Aufgaben) Verantwortung für Versionsmanagement-Infrastruktur. Seine Erfahrungen damit fasst er hier zusammen in Form eines fiktiven privaten Blogs, wie man es auf einer passwortgeschützten Webseite führen mag, erreichbar nur für einen vertrauten Freundeskreis.
Das kerP-Projekt, von dem dieses Blog berichtet, war ursprünglich eine interne Eigenentwicklung des jetzigen Auftraggebers. In der Hoffnung auf Einsparpotenzial wurde es vor Jahren an einen „big player“ übergeben („Outsourcing“).
Wie in vielen Outsourcing-Entwicklungen werden im kerP-Projekt zunächst einzelne Features vereinbart. Ein verantwortlicher „Feature Owner“ beim Kunden legt im Vorfeld gemeinsam mit einem Architekten des Lieferanten fest, wie das Feature konkret umzusetzen ist. Die resultierenden Absprachen werden in einem Vertrag fixiert.
Features gehen nicht einzeln in Betrieb, sondern es werden jeweils etliche zu einem Release zusammengefasst. Releases folgen einem strikten, vorgegebenem Takt: Alle zwei Monate wird ein neues kerP-Release produktiv.
Aus den Releaseterminen und den für die einzelnen Releases vereinbarten Features ergibt sich der detaillierte „Releasefahrplan“, in dem man lange im Voraus nachschauen kann, was wann fertig zu sein hat.
Das einzelne Release durchläuft eine klar definierte Prozesskette: Entwicklung, Tests, Nachbesserungen, erneute Tests, dann eine offizielle Abnahme und schließlich die Inbetriebnahme. In den Details der Prozesskette steckt langjährige Erfahrung.
Releasetaktung und Prozesskette gelten im kerP-Projekt als alternativlos.
kerP und die Wirklichkeit
Das kerP-Projekt ist fiktiv. Allerdings sind in das kerP-Blog reale Erfahrungen aus realen Projekten eingeflossen. Wer eines dieser Projekte mit dem Autor gemeinsam erlebt hat, dem wird vielleicht die eine oder andere Episode bekannt vorkommen. Wiedererkennbarkeit konkreter Projektgegebenheiten ist hier aber kein Ziel (und noch nicht einmal sonderlich erwünscht). In Blogepisoden, die im Kern aus Projekt A stammen, können durchaus Details aus Projekt B eingeflossen sein. Das erfundene Akronym kerP ist Programm: „kein einzelnes reales Projekt“.
Dagegen ist Wiedererkennbarkeit typischer Projektgegebenheiten erklärtes Ziel. In keinem geschilderten Detail hat sich der Autor weit von (irgendwo) erlebter Praxis entfernt.
Mein erstes kerP-Release
Vor einer Woche ging kerP-Release 1.23 in Produktion. So eine Inbetriebnahme ist ein ziemlicher Akt! Natürlich am Wochenende und nachts, gerne auch bei Nebel.
Wir hatten im Vorfeld ausführliche Releasenotes verfasst. Die vom Produktionsteam können lesen und tun das auch: Einige unklare Formulierungen hatten sie völlig zu Recht bemäkelt, das wurde nachgebessert. Nach einigem Hin und Her konnte eigentlich nicht mehr viel schief gehen.
Ging auch nicht. Es wurden trotzdem eine lange Nacht und ein kurzes Wochenende. Uff! Geschafft!
Am Montag hatten wir dann gut zu tun, um Dienstagmorgen dem Testteam Release 1.24 vor die Füße zu legen. Sie hatten ja gerade 1.23 in die Produktion entlassen und brauchten neues Futter.
Gleichzeitig sollte die heiße Entwicklungsphase für 1.25 anfangen. So war es jedenfalls geplant, und zwar seit Langem. Nur war das Entwicklungsteam mit 1.24 noch nicht fertig. Noch nicht ganz fertig. Ein klitzekleines Bisschen noch nicht ganz fertig…
Danach fragt im kerP-Projekt aber keiner. Ab dem Dienstag nach dem Releasewochenende wird das nächste Release getestet, Punkt. Das war schon immer so, und das bleibt auch so. „DoD? Schau in den Kalender!“
DoD und technische Schuld
Die „Definition of Done“ (DoD) bestimmt die Kriterien, die erfüllt sein müssen, ehe das Entwicklungsteam eine Software als „fertig“ meldet.
Manche solcher Kriterien haben mit der gewünschten Funktion der Software zu tun, werden vom Auftraggeber festgelegt und vom Testteam überprüft. Genauso wichtig sind Kriterien für die innere „Aufgeräumtheit“ und Wartbarkeit des Codes. Sie zu definieren und über sie zu wachen ist ein wichtiger eigener Verantwortungsbereich eines Entwicklungsteams. Aktuelle Entwicklungsmethodologien wie zum Beispiel „Scrum“ legen völlig zu Recht großen Wert auf diesen Aspekt.
Leider kommt er in releasegetakteten Projekten häufig zu kurz. Denn Releasetermin und Features werden weit im Voraus vertraglich festgelegt. Steht dann lange Zeit später das vereinbarte Entwicklungsende unmittelbar bevor, findet sich unter den vielen vereinbarten Features eigentlich immer das eine oder andere, das der Lieferant zunächst unterschätzt hat und das daher eben nicht rechtzeitig fertig zu werden droht.
Der nahe Abgabetermin übt dann Druck auf das Entwicklungsteam aus, die eigenen Kriterien wider besseres Wissen schleifen zu lassen. Die ehrliche Ansage „wir sind noch nicht fertig“ ist oft schlicht nicht vorgesehen.
Im Laufe der Releasezyklen schleichen sich so nach und nach unaufgeräumte, chaotische Anteile in den Code ein. Es entsteht ein langsam wucherndes Chaos, es entstehen „technische Schulden“.
So lange, bis doch irgendwann aufgeräumt wird, bleibt die Entwicklung zukünftiger Releases behindert. Das Projekt zahlt für seine technischen Schulden (sehr reale) Zinsen.
Wir hatten dann weiter gut zu tun den Rest der Woche. Bugfixes, Bugfixes, Bugfixes. Jeden Tag mindestens einen neuen Build für den Test, manchmal zwei.
Weekly merges
Seit meinem letzten Blogpost sind drei Wochen vergangen. Zeit, mal wieder von sich lesen zu lassen.
Die kerP-Entwicklung findet derzeit getrennt auf drei Branches statt, je einem für 1.23, 1.24 und 1.25.
Und wie die zunächst grün erstandene Banane notfalls erst im Obstkorb langsam gelb wird, reift auch 1.24 im Test vor sich hin: Bugreports hin, Fixes rein in den Branch, neue Builds zurück an den Test.
Nebenbei werden auch in der 1.23er Produktion noch Fehler gefunden, gefixt, und die Fixes in Produktion geschoben. Nicht oft, aber es kommt vor.
Natürlich müssen die Bugfixes aus 1.23 auch in 1.24 zur Verfügung stehen. In kerP 1.25 werden außerdem alle Verbesserungen aus 1.24 gebraucht. Dass alles da ankommt, wo es gebraucht wird, stellen wir mit regelmäßigen Merges sicher:
Wir veranstalten diese Merges wöchentlich, jeweils Dienstags den Merge 1.23 ➞ 1.24 und, seit es 1.25 gibt, Donnerstags 1.24 ➞ 1.25:
Wobei es mein Job geworden ist, den größten Teil dieser Merges durchzuführen. „Merges as a Service“ ☺.
Merges und ihr Umfeld
Ein „Merge“ verpflanzt Entwicklungsergebnisse aus einem Zusammenhang in einen anderen. In unserem fiktiven Blog wird von Merges von jeweils einem Codestrang/Branch auf einen anderen berichtet.
Wird man zum ersten Mal mit dem Konzept „Merge“ konfontriert, wundert man sich vielleicht, dass so etwas überhaupt funktionieren kann. Aber das tut es. Für erfahrene Entwickler ist ein „Merge“ ein normaler Vorgang, vor denen man keine Angst zu haben braucht.
Zumindest dann nicht, wenn das Umfeld stimmt. Zu einem Merges erleichternden Umfeld gehören nach den Erfahrungen des Autors:
- Eine wirksame Formatierungsrichtlinie („Style Guide“) Fehlt sie, so wird eine Code-Datei schnell mal von oben bis unten anders formatiert als vorher. Spätere Mergevorgänge werden dann durch sehr viele Änderungen aufgehalten, die nichts bedeuten und aus denen die eigentlichen, inhaltlich relevanten mühsam herauszusuchen sind.
- Mergefähige Dateiformate Textdateien sind im Allgemeinen gut zu mergen, insbesondere die Quelldateien gängiger Programmiersprachen. Für Binärdateien (dazu gehören insbesondere Office-Dateien) gilt das nur sehr eingeschränkt. Sind sie zu mergen, stehen häufig Ärger und Aufwand ins Haus. „Mergebarkeit“ ist dabei nicht als binäre Schwarz/Weiß-Eigenschaft zu sehen, es gibt durchaus Graustufen. So machen manche Konfigurationsdateien oder zentrale Tabellen gelegentlich mehr Arbeit, als das an sich gut mergebare Textformat zunächst vermuten ließe. Das kann zum Beispiel der Fall sein, wenn die Reihenfolg verschiedener Einträge innerhalb der Datei fachlich irrelevant und durch keine Konvention gesteuert ist und daher Neues gewohnheitsmäßig hinten anhängt wird.
- Ein merge-freundliches Versionsmanagementsystem Der Autor hat mehrfach leidvolle Erfahrungen mit Versionsmanagementsystemen gesammelt, die vermeindliche Mergerisiken von vorneherein minimieren wollen. Zum Beispiel mag eine solche Software parallele Änderungen an derselben Datei durch verschiedene Entwickler systemisch ausschließen, indem jede Datei vor jeder Änderung zu sperren ist. Betroffene Entwicklungsteams, zu denen der Autor gehörte, erlebten das jeweils nicht als hilfreich, sondern als einengende Behinderung normalen Vorgehens. Es wurde viel gestöhnt und geschimpft. In zwei konkreten Projekten kam es zu erfolgreichen Migrationen auf entwicklungsfreundlichere Versionsmanagementsysteme.
Normalerweise überträgt ein Merge alle Änderungen eines Codestranges in einen anderen, die es dort noch nicht gibt. Wer dagegen beim Merge einige Änderungen gezielt auswählt und andere nicht überträgt, „pflückt Kirschen“ (engl. „cherry picking“).
Dabei habe ich zur Zeit nur ein relativ oberflächliches Verständnis sowohl von der kerP-Fachlichkeit als auch von den Feinheiten des kerP-Codes. Trotzdem läuft das erstaunlich gut. Ich muss mir nur selten Rat und Hilfe holen.
Die großen Ausnahmen sind unsere Konfigurations-Excel-Dateien. Davon verstehe ich einerseits wirklich zu wenig, um die verschiedenen Änderungen beim Merge zusammenführen zu können. Glücklicherweise. Denn andererseits ist dieser Teil der wöchentlichen Merges einem Albtraum entsprungen.
Von diesen Konfig-Excel-Biestern gibt es ganze fünf Stück. Doch verursachen sie gefühlte ¾ des Mergeaufwands.
Was unseren normalen Code betrifft: Das Entwicklungsteam arbeitet eine Arbeitswoche lang die nötigen Änderungen in unseren Code ein, der aus elf Eclipse-Projekten besteht. Den Merge dieser gesammelten Änderungen ziehe ich Einzelperson anschließend an einem Nachmittag durch (und mache in aller Regel pünktlich Feierabend).
Dagegen werden für jeden Konfig-Merge zwei leidensfähige Teammitglieder abkommandiert, die sich parallel darum kümmern müssen. Sie brauchen zu zweit einen kompletten Tag dafür, wenn es gut läuft. Wenn nicht, auch anderthalb oder zwei Tage.
Gibt es in der Folge mergebedingten Ärger, liegt es fast immer an Problemen mit den Konfig-Excels.
Die sind aber auch ständig in Bewegung. Aus verschiedensten Gründen müssen sie immer wieder geändert und angepasst werden. Auch der Kunde arbeitet damit: Ein Feature Owner diktiert durchaus schon mal konkrete Inhalte, die wir dann aufnehmen.
Schon wegen der Kundensichtbarkeit ist es nicht so einfach, dieses leidige Excel-Format endlich durch etwas bequemeres zu ersetzen.
Mal ganz abgesehen davon, wo das Geld für so eine Aktion herkommen soll? Kein Feature Owner des Kunden mag sein Budget dafür hergeben. Unsererseits will der Projektleiter das Team natürlich auch nicht ohne konkrete Beauftragung (und Bezahlung!) arbeiten lassen.
Es sieht danach aus, als würde uns dieser Schmerzpunkt noch lange erhalten bleiben…
Schotten dicht!
Seit meinem letzten Post sind wieder zwei Wochen ins Land gegangen. Die letzten beiden Merges aus der Produktion reduzierten sich darauf, festzustellen, dass es dort keine Änderungen mehr gegeben hat. Auf dem 1.24er Branch ist noch etwas Bewegung, aber nicht mehr viel. Die eigentliche Musik spielt inzwischen da, wo sie hin gehört: Auf dem 1.25er Entwicklungsbranch.
Wobei es Probleme gibt. Denn für kerP 1.25 brauchen wir besonders viele Änderungen im Backend-Bereich. Immer wieder hakt dort etwas, und dann läuft die gesamte Software nicht mehr. Passiert das, sitzen die Frontendentwickler frustriert auf dem Trockenen: Ohne funktionierendes Backend können sie ihren Code nicht laufen lassen, nichts testen. Es dauert dann schon mal zwei, drei Tage, bis alles wieder im Lot ist.
Glücklicherweise haben wir einen Weg gefunden, das Problem einzugrenzen: Das Backend-Team wurde dazu verdonnert, auf einem Branch zu arbeiten. Mit Hilfe automatisierter Integrationstests überprüfen wir jede Nacht, ob der Branchcode als Basis für das Frontend taugt. Wenn ja, merge ich morgens in den Releasebranch. Wenn nicht, machen die Frontendentwickler mit einem älteren, funktionierenden Stand weiter.
Branch-Vielfalt
Mit einem „Branch“ (oder „Codestrang“) kann man einen Entwicklungsvorgang einerseits isoliert von allen anderen ablaufen zu lassen, andererseits die Isolation kontrolliert wieder aufheben. So stellt man Ergebnisse des einen Entwicklungsvorgangs dem anderen im passenden Augenblick zur Verfügung.
Es gibt verschiedenste gute Gründe für Branches. Der Autor empfiehlt als normales, bewährtes Vorgehen, dass das einzelne Entwicklungsteammitglied die Möglichkeit hat, bei Bedarf persönliche Branches im Versionsmanagement selbst anzulegen.
Typische Beispiele für Branches sind:
Release Branches
Software, deren Entwicklung durch Releases getaktet ist, benötigt je einen Branch pro Release.
Der zu einem Release gehörende Branch bleibt so lange aktiv, wie dieses Release unterstützt wird. Damit sind Releasebranches außerordentlich langlebig, vermutlich die langlebigsten Branches überhaupt. Um ein extremes Beispiel abseits kommerzieller Projekte zu nennen: Der Branch für den Linuxkernel 2.6.32 wurde am 27.9.2009 aufgemacht, war über vier Jahre später noch aktiv und soll bis Mitte 2014 weiter gepflegt werden.
Durch entsprechende Merges zwischen Releasebranches werden Bugfixes ausgetauscht. Das kann in beiden Richtungen geschehen, je nachdem, ob der Bug in einem älteren oder neueren Release zuerst gefunden und gefixt wurde.
Und „Trunk“?
In den Dokumentation verschiedener Versionsmanagementsysteme findet man Beispiele, bei denen verschiedene Branches von einem Hautstrang abzweigen. Je nach Terminologie heißt dieser Hauptstrang z.B. „Trunk“ oder „Master“.
In releasegetakteter Softwareentwicklung wird ein solcher Hauptstrang wenig gebraucht. Ihn zu benutzen empfiehlt sich nur für Material, das selbst nicht dem Releasetakt unterliegt. Dazu gehört zum Beispiel, was an Software und Skripten bei der Branchverwaltung oder bei den Merges hilft. Dazu gehört auch das äußere Setup für das automatisierte Testen oder die „Continuous Integration“. Dieses Setup legt fest, welche Releasebranches zur Zeit aktiv sind und automatisiert getestet werden. Dagegen sind die Tests selbst releaseabhängig und werden daher in den Releasebranches entwickelt, zusammen mit der Funktionalität, die durch sie getestet wird.
Feature Branches
Ein Feature kann in der Isolation eines spezifisch eingerichteten Branches entwickelt werden. Das empfiehlt sich, wenn noch nicht abschließend entschieden ist, ob das Feature überhaupt in die Software einfließen soll oder der Features-Code noch so unreif ist, dass er in seinem jetzigen Zustand die Gesamtsoftware noch nicht verbessern, sondern verschlechtern würde.
Ist schließlich das Feature sowohl beschlossen als auch reif genug, werden mit einem abschließenden Merge alle Ergebnisse des Featurebranches in einen passenden größeren Branch (z.B. Releasebranch oder, wo es ihn gibt, „Trunk“) übertragen. Der Featurebranch wird anschließend nicht mehr gebraucht.
Die Isolation der Featureentwicklung in einen eigenen Branch hat auch Nachteile:
Ein Featurebranch profitiert nicht von zentraler Test-Infrastruktur, die für den größeren Branch existieren mag.
Wechselwirkungen und Integrationsprobleme mit parallel ablaufenden anderen Entwicklungen fallen erst spät auf.
Der letztgenannte Nachteil kann zu einem gefährlichen Risiko mutieren, wenn mehrere Features kurz vor einem Release-Entwicklungsendetermin mehr oder weniger gleichzeitig gemergt werden. Passt dann nicht alles zusammen, wird es eng. Deshalb setzen Projekte mit Releasefahrplan Featurebranches eher selten ein.
Refactoring Branches
Manchmal ist innerhalb der Software etwas aufzuräumen oder systematisch umzustellen, ein „Refactoring“ steht an. Man richtet für ein anstehendes Refactoring gerne einen Branch ein, vor allem, wenn sich die Sache nicht mal eben an einem Tag erledigen lässt.
Analog zu den Gründen für Feature Branches empfiehlt sich ein Refactoring Branch, wenn man zu Beginn der Arbeiten noch nicht weiß, wie gut das Refactoring funktionieren wird (Refactorings werden durchaus experimentell unternommen und können auch scheitern), oder wenn während des Refactorings auf dem alten Vorgehen fundierender Code zunächst nicht mehr funktioniert, bis er auf das Neue umgestellt wurde.
Das Vorgehen an sich ist völlig analog zum Featurebranch. Manche Projekte behandeln Refactorings und Features sogar komplett gleich, sowohl in der Entwicklung als auch im Projektmanagement. Bei Outsourcing-Projekten ist diese Gleichbehandlung allerdings (leider) eher unüblich, Refactoring fristet oft ein Schattendasein.
Aufräumaktion
Letztens bat mich ein Kollege um einen Branch für ein Refactoring-Experiment. Ich habe mir kurzerhand eine passende Branchkonvention ausgedacht, sie dokumentiert und mit einer kurzen diplomatischen Aktion beim Projektmanagement jedem Entwickler die Erlaubnis verschafft, für eigene Zwecke Branches nach Bedarf selbst anzulegen.
Glücklicherweise dürfen im kerP-Projekt Entwickler Verantwortung übernehmen. Insofern geht das hier. Woanders habe ich auch schon erlebt, dass ein Entwickler sich jede kleine Codeänderung einzeln genehmigen lassen musste. „Code nach Vorschrift“ 😣.
Das Refactoring-Experiment des Kollegen war übrigens ein voller Erfolg. Er hatte erst zusammen mit unserem Senior-Developer eine Idee ausgetüftelt, um ein altes Problem wegzuräumen, das den Code an vielen Stellen plagte. Für eine Stelle haben die beiden das konkret durchgezogen und sind dann mit ihrer Lösung hausieren gegangen. Schließlich hatten sie Team und Management im Boot und sich die offizielle „Lizenz zum Aufräumen“ - redlich verdient!
Da kommt was auf uns zu…
Nun habe ich schon ziemlich lange nichts mehr geschrieben - es war einfach zu viel zu tun!
Dabei war es noch das Wenigste, dass wir inzwischen 1.24 heil in Produktion haben. 1.25 macht im Test ziemlich viel Probleme (nicht nur im Backend-Bereich). Aber auch das kann man noch als halbwegs normal akzeptieren.
Hauptsächlich haben wir inzwischen angefangen, kerP mit dem Allerheiligsten zu integrieren: Der Bestandssoftware des Kunden! Das wird ganz neue Funktionalitäten ermöglichen. Sie macht schon eine Menge Sinn, diese Integration! Spannende Zeiten!
Auf unserer Seite nennen wir die Integrationsunterstützung „Version 2.0“. Daran wird inzwischen heftig entwickelt.
Meine Merges sehen trotz alledem insgesamt immer noch so aus wie vorher. Nur die Versionsnummern haben sich geändert:
Auch beim Mergeplan mit Zeitachse haben sich eigentlich nur die Branchnamen verändert:
2.0 - geht gar nicht!
Inzwischen ist 1.25 in Produktion. Das war mühsam genug, und auch jetzt noch hören wir mehr Störgeräusche aus der Produktion als sonst.
So weit, so schlimm - aber so richtig kracht es bei der Integration von kerP 2.0 und der Bestandssoftware! Im Test funktioniert so gut wie gar nichts. Au Backe!
Glücklicherweise scheint es hauptsächlich am Team Bestandssoftware zu liegen. Die Kolleginnen und Kollegen hatten ihre Hausaufgaben schlicht nicht rechtzeitig fertig. Unser kerP 2.0 kommt vergleichsweise glimpflich weg.
Trotzdem: Die „Luft brennt“. Viel zu tun. Muss los! Mehr in den nächsten Tagen…
Merges im Quadrat
Aus Tagen sind nun doch (anstrengende!) Wochen geworden. Erst heute komme ich wieder zum Bloggen.
Inzwischen hat die Bestandssoftware geliefert. Die Schnittstelle ist in einer gesondert aufgesetzten Integrationstestumgebung angekommen, wo sie auf unser kerP 2.0 prallte, und umgekehrt. Was haben wir Builds in diese Umgebung ausliefern müssen!
Die traurige Nachricht: Über diese Testumgebung wird kerP 2.0 nicht hinauskommen. Bis zum nächsten anstehenden Releasetermin wird das alles einfach nicht rechtzeitig fertig. Keine Chance!
Deshalb hat das Management die Notbremse gezogen: Nach 1.25 wird ein Zwischenrelease 1.26 in Produktion gehen. Für dieses kerP 1.26 implementiert eine ausgesuchte Handvoll Leute auf die Schnelle eine ausgesuchte Handvoll besonders dringender Features.
Die hauptsächliche kerP-Entwicklungsteamkarawane ist inzwischen weitergezogen. Man arbeitet heftig an kerP 2.1, das in der Produktion auf 1.26 folgen soll - dann endlich mit Integration!
Natürlich müssen die Bugfixes aus 1.25 in alle anderen Branches auch hinein. Und sowohl die Features aus 1.26 und als auch die Bugfixes aus 2.0 müssen beide nach 2.1. Für mich bedeutet das, seit ein paar Wochen merge ich im Quadrat:
Am Montag beginnt die Mergewoche zunächst mit den Merges 1.25 ➞ 1.26 und 1.25 ➞ 2.0. Es hat sich als nützlich herausgestellt, diese beiden Merges kurz hintereinander stattfinden zu lassen und in beiden dieselben Änderungen aus 1.25 zu verarbeiten. Nun wird in 1.25 inzwischen nicht mehr viel geändert. Meistens schaffe ich beide Merges am Montag. Notfalls habe ich den Dienstag als Reserve.
Mittwochs merge ich 2.0 ➞ 2.1. Ist dieser Merge durch, sind neben allen anderen aktuellen 2.0er-Änderungen auch die Bugfixes aus 1.25 in 2.1 angekommen. Die hatte ich ja am Montag selbst von dort nach 2.0 geschafft.
Freitags kommt 1.26 ➞ 2.1 dran.
Das Ganze als Mergeplan mit Zeitachse, der auch zeigt, wie wir die Branches nacheinander eingerichtet haben:
Kirschpflückerei
Um mir keine doppelte Arbeit zu machen, achte ich darauf, Freitags nur die echte 1.26er-Arbeit zu übertragen. Die aus 1.25 hereingekommenen Änderungen lasse ich mit voller Absicht aus. Sie sind ja über 2.0 schon seit dem Mittwoch-Merge in 2.1 drin.
Damit das klappt, habe ich am Montag beim 1.25 ➞ 1.26 Merge schon darauf geachtet, das Mergeergebnis (besonders) sauber von anderen Änderungen zu trennen. Deshalb ist es einfach, dieses Material am Freitag gezielt wegzulassen. Ich „pflücke Kirschen,“ wie man so sagt.
Ich könnte es auch anders organisieren und das Material aus 1.25 über 1.26 nach 2.1 mergen. Das wäre aber mit mehr Arbeit verbunden. Denn es haben sich zwischen kerP 1.x und kerP 2.x einige Strukturen geändert. Daher sind die Merges 1.25 ➞ 2.0 und 1.26 ➞ 2.1 tendenziell aufwändiger als 1.25 ➞ 1.26 und 2.0 ➞ 2.1. Da ich das 1.25er Material über 2.0 nach 2.1 laufen lasse, brauche ich es nur einmal über die 1.x ➞ 2.x-Schwelle zu heben.
In ein paar Wochen geht 2.1 in den Test. Mal sehen, wie es sich machen wird. Ob es nochmal kracht und wir am Ende ein Release 1.27 zwischenschieben müssen?
Fazit
Damit endet das fiktive Blog. Es bleibt noch, ein Fazit zu ziehen. Oder drei?
Das erste Fazit ist: Das Leben auf dem Tanker ist möglich. Die im Blog geschilderten Vorgehensweisen haben den Praxistest bereits bestanden. Man kann so arbeiten.
Ein zweites Fazit ist: Das Leben mit einem Tanker ist teuer. Die Abstraktion „Release“ verführt dazu, dem Entwicklungsteam unfertige Software vor der Zeit aus den Händen zu reißen und nötige Aufräumarbeiten auf Sankt Nimmerlein zu vertagen. Beides kostet echtes Geld. Auch der Aufwand für ein komplettes Release („kerP 2.0“), das erst entwickelt, dann aber nicht eingesetzt wird, tut weh.
Zu fragen bleibt drittens: Trägt die Abstraktion „Release“?
Angeblich wird nur nach festgelegtem Plan sozusagen in großer Prozession Software durchs Hauptportal in die Produktionsburg getragen und dort feierlich entgegen genommen. So die Theorie.
In der Praxis gibt es aber auch noch den Lieferanteneingang: Für Bugfixes. Im direkten Vergleich ist deutlich weniger Getöse nötig, um einen Bugfix in die Produktion zu bringen. Zählt man sie mit, gibt es in Wirklichkeit deutlich mehr Softwarelieferungen, als die, von denen der offiziellen Releasefahrplan weiß.
Und diese zusätzlichen Lieferungen funktionieren. Bugfixes machen in der Praxis keinen Ärger. Warum nicht? Weil es sich um kleine, überschaubare Änderungen handelt.
Alternativen zum althergebrachten Releasemodell greifen genau diese Erfahrung auf und gehen einen Schritt weiter: Schafft man es, auch die eigentliche Funktionalität statt in großen, seltenen Releases häufiger und in kleineren, überschaubaren Häppchen auszurollen, wird manches Getöse überflüssig. Alle Features können dann geordnet in der Entwicklung zu Ende reifen, statt als grüne Testbananen mühsam mit Hilfe von Bugfix-Nachlieferungen. Dabei bekommt die Produktion die meisten Features eher: Nicht erst beim nächsten Releasetermin, sondern jedes Feature schon dann, wenn es fertig ist. Und sogar - da die Features im geordneten Entwicklungsprozess gereift sind und nicht durch chaotische Bugfixes während des Tests - in besserer Qualität.