Agiler Projekteinsatz

Software-Entwicklung: Einsatz eines Versionsverwaltungssystems in der Praxis

Ausgewählte Strategie mittels Versionsverwaltungssystem

Im agilen Entwicklungsumfeld hat sich in der Praxis eine Kombination aus "Develop on Mainline" und "Branch for Release" bewährt. Diese unterstützt einen CI-Prozess optimal und eignet sich bestens für die typische Aufteilung der Entwicklung in kleine Teilaufgaben, die nur einige Stunden bis wenige Tage dauern. Die regulatorischen Anforderungen an die Entwickler sind einfach und die Einhaltung der notwendigen Richtlinien für alle Beteiligten verhältnismäßig einfach - agile Entwicklung und CI-Prozess ergänzen sich also bestens. Durch gezielte Vermeidung unnötiger Merging-Vorgänge, die in den beiden anderen Strategien notwendig sind, lassen sich Entwicklungstermine zudem deutlich besser planen. werden. Der Aufwand für umfangreiche und komplexe Merging-Vorgänge, die bei "Branch by Feature" und bei "Branch by Team" entstehen, können nur schlecht vorhergesagt werden. Anhand von Subversion wird die Verwendung von Branches, Tagging und Merging vorgestellt.

Ablauf: Beispiel für die Umsetzung der "Develop on Mainline" und "Branch for Release"-Strategien.
Ablauf: Beispiel für die Umsetzung der "Develop on Mainline" und "Branch for Release"-Strategien.
Foto: Trivadis AG

Das Bild zeigt eine mögliche Release-Strategie mit zwei parallelen Release-Branches. Die Entwicklung arbeitet an einer Version 2.1 auf dem Trunk. Der Tag "1" markiert einen erfolgreichen Build, der als Branch für einen Release 2.1 genutzt werden kann. Dieser kann beispielsweise nach einem erfolgreichen Build des CI-Servers erzeugt werden. Dieser Build erfüllt alle Qualitätskriterien für einen Release 2.1. Da auch alle notwendigen Features für Version 2.1 bereits implementiert sind, kann ein Branch auf der Basis des Tags "1" gezogen werden. Mit Branch 2.1 werden nur noch Bugfixes durchgeführt.
Alle Änderungen in dem Branch werden zeitnah (am gleichen Tag) in den Trunk übertragen (siehe rote Pfeile). Bugfixes aus dem Trunk in den Branch werden nur übertragen, wenn sie unumgänglich sind (siehe gestrichelte rote Pfeile). Der Grund: Es besteht die Gefahr, dass neue Features ungewollt aus dem Trunk in den Branch übertragen werden. Mit dem Tag "R" wird ein Revisionsstand in Subversion als Release markiert. Üblicherweise wird im Namen des Tags der exakte Release gekennzeichnet, wie "Rel. 2.1". In diesem Branch können in schneller Folge neue Releases erstellt und mit einem Tag markiert werden, wie beispielsweise Release 2.1.1. Solange ein Release aus diesem Branch im Einsatz ist, lassen sich hier Bugfixes erstellen und neue Releases produzieren. Die Tags markieren jedoch auch die Version, die per Rollout bei den Kunden zum Einsatz kommt.

Im Trunk wird nach den 2.1-Branching an der Version 2.2 gearbeitet, sprich neue Features für diese Version entwickelt. Der Tag "2" markiert wiederum einen erfolgreichen Build, der als Release 2.2 genutzt werden kann. Jetzt wird der Branch 2.2 erzeugt und die Entwicklung kann nun den Release 2.2 in diesem Branch fertigstellen. Ein erfolgreicher Build im Branch wird als offizielles Release 2.2 markiert und ausgerollt. Sobald alle Installationen aus dem Branch 2.1 durch einen Release aus dem Branch 2.2. ersetzt worden sind, kann der Branch 2.1. als "final" markiert werden. Dort finden dann keinerlei Entwicklungsaktivitäten mehr statt. Bei diesem Vorgehen existieren innerhalb eines festgelegten Zeitraumes drei Entwicklungslinien gleichzeitig: Mainline, Branch 2.1 und Branch 2.2.

Ablage von Sourcen in einem Versionsverwaltungssystem

Als Versionsverwaltungssystem hat sich in der Praxis Subversion als geeignet erwiesen. Analog zu einem klassischen Dateisystem kann die Software zum Archivieren von Dateien mehrere Festplatten, so genannte Repositories, verwenden. Diese sind im Grunde wie eine Festplatte zu sehen, die im Dateiverzeichnisbaum eingehängt wird - jedoch eine eigene Versionshistorie besitzt. Subversion betrachtet ein Repository als eigenständige Verwaltungseinheit.

In Subversion wird der Source Code für mehrere, zum Teil sogar von einander abhängige Projekte des gleichen Entwicklungsteams verwaltet. Bevor das Entwicklungsteam mit der Code-Produktion beginnen kann, muss die Verteilung und die Struktur der Sourcen der Produkte im SVN festgelegt werden. Die Beteiligten stehen nun zunächst vor den Entscheidung, ob sie ein oder mehrere Repositories für die Verwaltung des Source Codes verwendet wollen und wie die Ablagestruktur für das Multiprojektvorhaben aussehen soll.

Ein oder mehrere Repositories?

Bei mehreren Produkten oder Projekten stellt sich die Frage, ob ein Repository für alle Produkte (Variante A) oder ob pro Produkt ein Repository (Variante B) angelegt werden soll.

Unterschiedliche Ansätze: Ein Repository für alle Produkte (Variante A) oder pro Produkt ein Respository (Variante B)?
Unterschiedliche Ansätze: Ein Repository für alle Produkte (Variante A) oder pro Produkt ein Respository (Variante B)?
Foto: Trivadis AG

Die Unterschiede zwischen beiden Varianten sind aus technischer Sicht eher gering: Beispielsweise werden Berechtigungen pro Repository gepflegt, die Revisionsnummern getrennt verwaltet und ein Merging von Sourcen nur innerhalb eines Repositories unterstützt.

Unterschiede zwischen den Varianten A und B:

  • Berechtigungen in Variante A werden mehrere Produkte pro Repository verwaltet. In SVN können dazu Read/Write-Rechte pro Repository oder Pfad vergeben werden.

  • Branching und Merging beziehen sich immer auf ein einzelnes Repository - eine Zusammenarbeit mit weiteren ist nicht ohne Weiteres möglich.

  • Jedes Repository besitzt eine eigene Revisionsnummer. Sie wird erhöht, sobald ein Commit durchgeführt wird. Dies bedeutet bei Variante A, dass zwei aufeinander folgende Commits zu einem Produkt nicht zwingend aufeinander folgende Revisionsnummern haben müssen, da unter Umständen bereits ein Commit zu einem anderen Produkt stattgefunden hat. In Variante B sind die Revisionsnummern kontinuierlich bei einem Produkt.

Empfehlung: Variante A

Variante A verursacht einen deutlich geringen administrativen Aufwand als Variante B, da nur ein Repository verwaltet werden muss. Alle Produkte innerhalb des Repository besitzen zunächst die gleichen "Einstellungen" - wie beispielsweise Berechtigungen. Die Möglichkeit das Branching und Merging innerhalb des Repository über mehrere Produkte hinweg zu nutzen, bietet zudem deutlich mehr Flexibilität für zukünftige Softwareprojekte. Die konkrete Revisionsnummer für ein Produkt wird hingegen nur an wenigen Stellen benötigt - beispielsweise beim Vergleich von Revisionen (aktueller Stand vs. vorheriger Stand) oder beim Erzeugen eines Branches oder Tags. Letztlich fällt Entscheidung für Variante A: Geringer administrativer Aufwand bei größter Flexibilität.

Struktur innerhalb des Repositories

Nun muss die Ablagestruktur der Sourcen innerhalb eines Repositories festgelegt werden. In SVN gibt es bei beiden Varianten keine technischen Unterschiede. Die Variante 1 trennt die Produkte sehr anschaulich, während die Variante 2 die Eigenschaften des Versionsverwaltungssystems wie Tags und Branches betont.

Welche Struktur der Sourcen soll innerhalb eines Repositories bestehen?
Welche Struktur der Sourcen soll innerhalb eines Repositories bestehen?
Foto: Trivadis AG

Um alle Sourcen zum jeweiligen Produkt zu erhalten muss aus Sicht eines Entwicklers in Variante 1 nur das Produkt-Verzeichnis runtergeladen werden - in Variante 2 sind es drei verschiedene. Betrachtet man allerdings auch die Branches und Tags, dann ist Variante 2 möglicherweise sinnvoller, da dort der Entwickler nur den Trunk eines Produktes auswählen kann und damit die Branches und Tags Verzeichnisse nicht laden muss. Dies macht sich besonders dann bemerkbar, wenn umfangreiche Branches und Tags vorhanden sind. Auch ein weiterer Umstand spricht eher für Variante 2: Bestehen Produkte aus einzelnen Komponenten und ist deren indiviuduelle Weiterentwicklung geplant, sehen die Varianten wie folgt aus:

Was passiert, wenn zusätzliche Komponenten eingeführt werden?
Was passiert, wenn zusätzliche Komponenten eingeführt werden?
Foto: Trivadis AG

Das Entwicklerteam hat die Variante 2 bevorzugt, da die Organisation der Sourcen verständlicher ist und der Entwickler den Trunk eines Produktes problemlos kopieren kann, ohne die Tags und Branches der darunter liegenden Komponenten wie cmp1 oder cmp2 automatisch zu übernehmen.

Inhalt des Repositories definieren

Spätestens nachdem das Repository angelegt und die grobe Struktur implementiert ist, stellt sich die berechtigte Frage, was im Repository versioniert verwaltet werden soll und was dort nicht hineingehört. Diese lässt sich relativ leicht beantworten: Grundsätzlich sollten alle Elemente, die zur Erstellung oder Beschreibung eines Softwareproduktes notwendig sind, im Repository abgelegt werden. Andere Bestandteile des Projekts werden nicht im Versionsverwaltungssystem abgelegt sondern in einem Content Management System (CMS). Dazu gehören Projektpläne und -Listen sowie alle weiteren Unterlagen, die nicht unmittelbar zum Entwicklungsprozess gehören. Die folgende Tabelle gibt einen Überblick über den Verwaltungsort diverser Projekt-Artefakte:

Orte zur Verwaltung von Projekt-Artefakten für die agile Softwareentwicklung

Repository

Content Management System

Source-Codes

Binäre-Auslieferungsdateien

Build-Skripte

Generierte Dateien

Konfigurationsdaten

Protokolle von Meetings

Installationsskript

Projektpläne

Release-Notes

Liste offener Punkte

Testspezifikatin und Testdaten

Risikolisten

Anforderungsdokumente

Schnittstellenverträge

Benutzerdokumentation

Architektur- und Designdokumente

Entwicklungshandbuch

Neben den oben genannten existieren weitere Artefakte, die je nach Projekt unterschiedlich behandelt werden. Dazu zählen beispielsweise:

  • Werkzeuge wie IDE, Compiler und Build-Tools

  • Betriebssystem auf dem entwickelt wird oder auf dem die Software installiert wird

  • Libraries und Frameworks

Diese Bestandteile passen auf Grund ihrer Größe oder ihrer Änderungshäufigkeit nicht in ein Repository oder ein Content Management System (CMS). Hier bietet sich eine manuelle, dateibasierte Verwaltung auf einen Netzlaufwerk an, dass von allen Projektbeteiligen gelesen, aber nicht geschrieben werden kann. In den Release-Notes oder im Entwicklungshandbuch sollte jedoch unbedingt ein eindeutiger Verweis auf den Ablageort dieser Artefakte hinterlegt sein. Im Falle von Java oder .Net als Entwicklungsplattform können Libraries und Frameworks in speziellen Repositories, wie beispielsweise Nexus oder Nuget, verwaltet werden.

Fazit

Für den Umgang mit Versionskontrollsystemen in der agile Softwareentwicklung bietet sich eine Kombination von "Develop on Mainline" und "Branche for Release". Auf der Basis dieser Strategien kann ein erfolgreicher CI-Prozess etabliert werden: Kurze Entwicklungsaufgaben, die im agilen Vorgehen nur eine geplante Dauer von ein paar Stunden bis wenige Tage haben, unterstützen den täglichen Build der Software und fördern die ständige Verfügbarkeit der Software für Tests und Kundendemonstrationen.

B&M-Verfahren

Vorteile

Nachteile

Develop on Mainline

Passende Basis für einen CI-Prozess
Wenig Merging
Einfachheit des Verfahrens

Erhöhter Aufwand bei größeren Entwicklungsaufgaben

Branch for Release

Sehr gute Ergänzung zu "Develop on Mainline"
Mehrere gleichzeitige Releases möglich

Bei Merges on der Mainline in den Release-Branch können unbeabsichtigt Features in den Release-Branch wandern

Branch by Feature

Features werden unabhängig voneinander in eigenen Branches entwickelt
Geeignet für große Entwicklungsteams

Unpassende Basis für einen CI-Prozess
Erhöhter Merging Aufwand
Im Vergleich komplexeres Verfahren

Branch by Teams

Jedes Team besitzt eigenen Branch, somit weniger Branches als bei Branch by Feature
Geeignet für große Entwicklungsteams

Unpassende Basis für einen CI-Prozess
Erhöhter Merging-Aufwand
Im Vergleich komplexeres Verfahren