Herausforderung Brownfield, Teil 2: Das Sicherheitsnetz aufspannen

Seite 3: Continuous Integration

Inhaltsverzeichnis

Die Tatsache, dass alle Dateien in einem zentralen VCS hinterlegt sind, bedeutet allerdings noch nicht, dass dort tatsächlich alle relevanten Dateien abgelegt sind. Schließlich könnte es sein, dass ein Mitarbeiter eine benötigte Datei nur auf seinem lokalen Arbeitsplatzrechner gespeichert hat. Das fällt so lange nicht auf, wie er dafür zuständig ist, das betreffende Projekt auf seinem Rechner zu übersetzen. Sobald er im Urlaub ist, geht nichts mehr. Niemand weiß, was zu tun ist, um das Projekt zu übersetzen und auslieferungsfertig zu machen. Dann fürchten Entwickler oft den Aufwand: Jeder drückt sich davor, solange es eben geht, die Software zur Auslieferung vorzubereiten.

Die Vorbereitungen zur Auslieferung eines Softwareprodukts sind mehr als das bloße Übersetzen des Quellcodes. Es sind die zum Produkt gehörigen Dateien zusammenzustellen, es ist ein Set-up zu generieren, Datenbank-Skripte müssen erstellt werden. Auch Verwaltungsaufgaben fallen an: Das Produkt muss eine Versionsnummer erhalten. Sie sollte sich in allen benötigten Binärdateien wiederspiegeln. Die Quelldateien sind in der Versionskontrolle zu markieren, damit sich der Versionsstand später reproduzieren lässt. Schließlich sind vielleicht eine Vorlage für das Brennen von CDs zu erstellen oder das Produkt zum Download bereitzustellen. Solange Projekte diese Schritte jedes Mal in Handarbeit durchlaufen, kann von Produktionseffizienz keine Rede sein.

Der Integrationsprozess wird daher in vielen Projekten zu selten durchgeführt. Auch hier ist die Lösung naheliegend: Sie lautet Automatisierung. Wenn der Integrationsprozess soweit automatisiert ist, dass dafür kein Spezialwissen erforderlich ist, sondern nur jemand auf einen Knopf drücken muss, hat er seinen Schrecken verloren. Dann lässt sich der Prozess oft ausführen, weil damit kein großer Aufwand mehr verbunden ist – im Idealfall mit jeder Änderung, die ein Projekt im VCS erfährt. Schließlich ist nur so sicherzustellen, dass sich der aktuelle Stand des Projekts übersetzen und alle Teile integrieren lassen.

Damit der Integrationsprozess leicht zu automatisieren ist, ist zunächst dafür zu sorgen, dass die Projekte im VCS möglichst keine externen Abhängigkeiten haben. Damit ist gemeint, dass ein Projekt alle zur Übersetzung erforderlichen Dateien und Bibliotheken enthalten sollte. Dann reicht es aus, das Projekt aus der Versionskontrolle abzurufen, und es lässt sich übersetzen. Sind externe Abhängigkeiten erforderlich, kann die Übersetzung nur auf solchen Rechnern erfolgen, die die Abhängigkeiten unterstützen. Meist bedeutet das, dass man dort Softwareprodukte installieren muss. Das lässt sich nicht in allen Fällen vermeiden, sollte sich aber reduzieren lassen. Im Idealfall ist es nur erforderlich, die Kommandozeilenwerkzeuge der verwendeten Entwicklungsumgebung zu installieren. Bibliotheken, die man nicht im eigenen Haus entwickelt, sollten im günstigsten Fall im jeweiligen Projekt abgelegt sein. Dann gelangen sie beim Abrufen des Projekts aus dem VCS gleich mit auf die Festplatte des Entwicklers, sodass dort keine zusätzliche Installation erforderlich ist.

Das Ablegen externer Abhängigkeiten in die Verzeichnisstruktur des Projekts löst auch ein Versionsproblem: Nutzt man eine Bibliothek im Laufe der Zeit in unterschiedlichen Versionsständen, liegt in der Versionskontrolle beim jeweiligen Projekt automatisch immer die richtige Version. Somit ist das wieder eine Voraussetzung dafür, dass sich auch ältere Versionen des Produkts aus der Versionskontrolle reproduzieren lassen.

Nachdem Teams sichergestellt haben, dass möglichst alle Abhängigkeiten des Projekts in der Versionskontrolle vorhanden sind, lässt sich der Build-Prozess in der Regel leicht automatisieren. Ziel ist es, ihn mit einem Kommandozeilenbefehl ausführen zu können. Es dürfen keine interaktiven Eingriffe erforderlich sein. Das unterstützen moderne Entwicklungsumgebungen in der Regel. Bei älteren Entwicklungswerkzeugen, es geht ja schließlich um Brownfield-Projekte, kann das schon mal schwieriger sein. Meist lässt sich aber ein Weg finden, den Build-Prozess zu automatisieren.

Je nach verwendeter Entwicklungsumgebung kommen Programme wie make, msbuild und NAnt zum Einsatz beziehungsweise Zusatzprodukte wie FinalBuilder. Damit lassen sich die zur Integration des Produkts erforderlichen Schritte vollständig automatisieren. Am Ende ist es Fleißarbeit, alle Aspekte des Erstellungsprozesses zu automatisieren. Vor allem braucht das niemand neu "erfinden", es gibt genügend Literatur und Hinweise im Internet, die den Vorgang detailliert beschreiben.

Liegt ein automatisierter Build-Prozess vor, wird im nächsten Schritt ein Rechner für diesen Prozess abgestellt. Er hat keine andere Aufgabe, als bei Bedarf den Build-Prozess auszuführen. "Bei Bedarf" bedeutet mit jeder Änderung in der Versionskontrolle. Dieser als Continuous Integration bezeichnete Vorgang sorgt dafür, dass sich niemand mehr um den Build-Prozess kümmern muss. Er läuft automatisiert ab und sorgt dafür, dass zum aktuellen Stand des Projekts ein aktuelles Set-up des Projekts vorliegt. Vor allem sorgt Continuous Integration dafür, dass sich Probleme beim Build und bei der Integration sofort entdecken lassen.

Um den kontinuierlichen Integrationsprozess in Gang zu bringen, installiert man auf der Build-Maschine ein entsprechendes Programm. Dazu steht eine Fülle an Produkten zur Auswahl, oft in Abhängigkeit von der verwendeten Entwicklungsumgebung. Die Palette reicht von reinen Open-Source-Lösungen wie CruiseControl oder Hudson über kommerzielle Produkte, die mit Einschränkungen kostenlos zu verwenden sind, wie JetBrains' TeamCity, bis hin zu Produkten wie Microsofts Team Foundation Server (TFS).

Es ist wichtiger, den Continuous-Integration-Prozess so schnell wie möglich mit Leben zu füllen, statt auf das am besten integrierte Tool zu setzen. Denn die Integrationstiefe von Tools hat ihren Preis: Je leistungsfähiger ein Produkt ist, desto aufwendiger ist seine Installation und Konfiguration. Ferner führt ein hoch integriertes Tool dazu, dass immer nur eine Weiterentwicklung des Gesamtsystems möglich ist. Dagegen lassen sich beim Einsatz einzelner spezialisierter Werkzeuge die einzelnen Bausteine getrennt weiterentwickeln oder sogar austauschen. Es geht nicht darum, die eierlegende Wollmilchsau zu finden, sondern den CI-Prozess zu beginnen. Mit darauf spezialisierten Produkten ist das reine Tooling keine Hexerei und schnell erledigt. Die Hoffnung auf hohe Integrationstiefe wird jedoch häufig nicht erfüllt, weil das einen enormen Aufwand nach sich zieht.