Parallele Softwareentwicklung spielend meistern
Seite 3: Main-Branches
Main, Main, Main ...
Da ein Main-Branch für alle parallel entwickelten Versionen nicht genügt, wird als Lösungsansatz für das zuvor geschilderte Problem pro Version ein zusätzlicher Main-Branch erstellt. Somit ist die regelmäßige Integration zwischen Main- und Dev-Branches sichergestellt, und es kann bei Bedarf ein Release erstellt werden, wie Abbildung 3 zeigt.
Durch die Verwendung eines Main-Branches pro zu entwickelnder Version können regelmäßige Merges zwischen Main und Dev erfolgen, ohne die anderen, parallelen Versionen zu beeinträchtigen. Zu jeder Zeit ist ein Release einer stabilen Version von Main möglich (1). Werden kontinuierlich mehrere Versionen entwickelt, ist die Integrität von Main innerhalb einer Releaseversion weiterhin gewährleistet (2). Werden Features erst nach dem Branching der nachfolgenden Versionen (im Beispiel Version 2.0) in der aktuellen Version (im Beispiel Version 1.0) fertiggestellt, werden diese durch ebenso regelmäßige Integration zwischen den verschiedenen Main-Branches in die späteren Versionen implementiert (3). Auch das Bereinigen von Fehlern in ausgelieferten Versionen ist weiterhin möglich. Die Codeänderungen gelangen durch die regelmäßige Integration in die anderen, vorhandenen Main- und Dev-Branches respektive Softwareversionen (4).
An diesem einfachen Beispiel lässt sich erkennen, dass durch die Integration zwischen den einzelnen Main-Branches erheblicher, zusätzlicher Merge-Aufwand entsteht. In großen Projektteams sind zusätzliche Team-, Feature- oder Integrations-Branches keine Seltenheit, die den Integrationsaufwand zusätzlich erhöhen. Im Einzelfall gilt es abzuwägen, ob das dargestellte Branching-Konzept den zusätzlichen Aufwand rechtfertigt. Letztlich hat bei umfangreichen Codeänderungen, mehreren Softwareversionen und regelmäßigen oder auch kurzfristigen Releases das Branching-Konzept eindeutig seine Vorteile.
Die Bälle in die Hand nehmen
Es empfiehlt sich, bei der Adaption eines geeigneten Branching-Konzepts die Entwicklungsabteilung von Beginn an zu integrieren. Denn das Konzept wirkt sich stark auf die tägliche Arbeit aller Nutzer des Versionsverwaltungssystems aus. Des Weiteren lassen sich vor der endgültigen Einführung gemeinsam Anwendungsfälle erarbeiten und prototypisch implementieren.
Zunächst gilt es, die Frage zu klären, was ein Branch aus Abbildung 3 enthält. Wenn in dem Main-Branch das vollständige Softwareprodukt enthalten ist – also neben Quellcode auch sämtliche Dateien, die für ein Release notwendig sind –, ist zu entscheiden, ob beim Anlegen eines Entwicklungs- oder Feature-Branches der komplette Inhalt von Main Bestandteil ist oder nur die tatsächlich relevante Dateien. Im ersten Fall können erheblich mehr Nutzer den Branch für unterschiedliche Implementierungsaufgaben verwenden. Die zweite Variante wird perspektivisch dazu führen, dass die Anzahl der Branches erheblich zunimmt.
Werden Server-Builds verwendet, empfiehlt sich ebenso die Verwendung von Variante 1, da somit der Konfigurationsaufwand geringer ist. Letztlich gilt das Motto: "So wenig Branches wie möglich, so viel wie nötig." Allerdings nimmt je nach Architektur des Softwareprodukts respektive des Inhalts eines Branches die Dauer für das Abrufen der Dateien aus dem Repository zu.
Aus technischer Sicht ist relevant, wie sich das Erzeugen von Branches auf die Größe der Datenbank des Versionsverwaltungssystems auswirkt. Beim Erstellen eines neuen Branches im TFS wird lediglich auf die ursprünglichen Dateien des Eltern-Branches verwiesen. Erst wenn sich Änderungen an einer Datei ergeben – unabhängig ob Text- oder Binärdatei – wird ein Datensatz mit den enthaltenen Änderungen (Delta) angelegt. Weiterführende Informationen erläutert Bill Heys ausführlich.
Abhängig vom verwendeten Versionsverwaltungssystem existieren verschiedene Möglichkeiten, das Branching-Konzept im Entwickleralltag anzuwenden. Im Allgemeinen lässt sich das Anlegen unnötiger Branches durch entsprechende Berechtigungen verhindern. Ebenso empfiehlt es sich, Verantwortlichkeiten für existierende Branches zu definieren, sodass jeder Entwickler bei Bedarf den Ansprechpartner kontaktieren kann. Zwischen Branch-Verantwortlichen und Projektleitung lässt sich gemeinsam entscheiden, ob ein Branch für anstehende Änderungen genutzt werden kann oder ein neuer Branch zu erzeugen ist.
Des Weiteren lässt sich die langwierige Fehlersuche bei nicht funktionsfähigen Versionsständen durch Build-Server verringern. Wer den Satz "Bei mir funktioniert es aber" regelmäßig hört, kennt das Problem. Um die Qualität des Quellcodes in den einzelnen Branches zu gewährleisten, bietet der TFS verschiedene Auslöser, um zentrale Builds zu starten. Neben manuell ausführbaren Builds sind Continuous Integration Builds (starten nach jedem Check-In – bei Subversion und Git Commit), Rolling Builds (Build aller Check-Ins innerhalb eines zeitlichen Intervalls), Gated Check-Ins (Check-In erfolgt nur bei erfolgreichem Build) und Scheduled Builds (Builds zu festen Zeiten, zum Beispiel Nightly Builds) möglich. Infolgedessen lassen sich für jeden Branch entsprechende Quality Gates definieren.
Für den Main-Branch bieten sich Gated Check-Ins an, um die jederzeit lauffähige Version zu garantieren. Auf Entwicklungs- oder Feature-Branches würde dies die Arbeit eher behindern, wonach Rolling und Scheduled Builds die bessere Wahl sind. Wie erwähnt, lässt sich die Integrität von Main dadurch sicherstellen, dass keine Entwicklung direkt auf dem Main-Branch erfolgt.
Was nützt jedoch das beste Branching-Konzept, wenn sich keiner daran hält? Im Idealfall wird ein bereits vorhandener Spickzettel für Entwickler um die elementaren Punkte des verwendeten Branching-Konzepts erweitert.