Es bedarf großer Umsicht, wenn viele Software-Entwickler gemeinsam an einem Projekt arbeiten. Führt einer von ihnen einen Bug an einer selten genutzten Stelle im Code ein, den Anwender oder Tester erst etliche Revisionen später entdecken, gestaltet sich das Bugfixing besonders schwierig.
Build-Umgebungen helfen, um aus dem Quelltext lauffähige Programme zu erzeugen, Source-Code-Managementsysteme (SCM), um den Programmtext zu versionieren und zu verteilen, Test-Frameworks, um das Projekt auf syntaktische, statische, logische und funktionale Fehler zu prüfen. In jedem Bereich gibt es eine Handvoll Werkzeuge, um Code für C, C++, Java oder PHP zu verwalten.
Die einzelnen Werkzeuge kitten Entwickler gerne mit Shellskripten und Wrappern zusammen - doch das gerät schnell aufwändig. Die im Kasten "Continuous Integration (CI)" erläuterte junge Disziplin macht sich diese Koordination zur Aufgabe. Es existiert inzwischen eine ganze Reihe fertiger Werkzeuge für Continuous Integration. Wer das hier vorgestellte und im Java-Kontext bei Sun entstandene Hudson [1] nicht verwenden möchte, findet Alternativen bei Cruise Control [2] oder Apache Gump [3] .
|
Teamarbeit ist in der modernen Software-Entwicklung verbreitet. Die wenigsten Projekte zieht ein einzelner, einsamer Hacker durch, selbst kleine Projekte kommen mit einem Team von drei bis zehn Personen besser voran. Das liegt nicht nur an der simplen Verteilung der Arbeitslast. Diskussionen im Team über das Wohin und Wie sind genauso wertvoll wie das Nutzen unterschiedlicher Fähigkeiten der Teammitglieder vom Software-Entwurf bis hin zur Icon-Gestaltung. Aufwand durch Teamkoordination
Doch Teamarbeit gibt es nicht umsonst, neben den typischen Problemen menschlicher Zusammenarbeit ist auch eine Reihe technischer Hürden zu bewältigen. Denn auch bei klarer Aufgabenteilung kann eine kleine Änderung die Stabilität der gesamten Software gefährden. Besonders kritisch wird es, wenn das Problem nicht zeitnah entdeckt wird. Die Ursache für ein Problem zu entdecken gerät überproportional aufwändiger, je mehr Änderungen seither erfolgt sind. Dieser Zustand ist für das Projekt sehr gefährlich, denn es demotiviert alle Mitarbeiter extrem. Freiwillige Teammitglieder bei offener Software springen dann leicht ab, von den finanziellen Folgen bei kommerziellen Projekten gar nicht zu reden. Mit CI regelmäßig auf Vollständigkeitprüfen
Continous Integration (CI) hält die Entwicklung in ruhigen Bahnen. Dahinter steckt die Idee, die ganze Software nach jeder Änderung oder wenigstens sehr regelmäßig zu kompilieren und zu testen. Hiermit lassen sich Qualitätsprobleme zeitnah entdecken und die Ursachen sofort abstellen. Die populäre Idee stammt aus dem Umfeld der agilen Software-Entwicklung.
Im Idealfall startet das CI-Tool nach jedem Einchecken einen Durchlauf, spätestens jedoch einmal täglich (Nightly Build). Fällt der neue Stand beim Kompilieren, Linken oder Testen durch, ist der Fehler wesentlich einfacher zu finden, als wenn die Arbeit von mehreren Entwicklern nur alle Jubeljahre zusammengefahren wird. Zwei Punkte sind dafür wesentlich: Das Buildsystem (Make, Ant) muss das Kompilieren ohne manuellen Eingriff ermöglichen und die Tests müssen die Software möglichst gut abdecken.
Der Arbeitsaufwand in einem Durchlauf unterscheidet sich von Projekt zu Projekt. Einfache Projekte sind mit Kompilieren und Testen auf einem Rechner in den Griff zu bekommen. Schwierig wird es, wenn ein Projekt aus mehreren Teilen - etwa Bibliotheken - besteht oder gar plattformübergreifend arbeitet. Hier sind die Schritte parallel auf mehreren Plattform (Hardware, Linux-Distributionen, Kompilerversion) zu testen. Und schließlich helfen neben dem Unit-Test auch Werkzeuge zur statischen Codeanalyse dabei, rechtzeitig problematische Stellen zu finden. Automatisierung schafft definierte Abläufe
Kaum ein Entwickler wird diese Schritte mehr als zwei- oder dreimal per Hand durchlaufen wollen. Auf Dauer ist Automatisierung nötig. Dabei helfen spezielle Werkzeuge zur Continous Integration, die den Ablauf immer wieder kontrolliert durchlaufen, die Ergebnisse aufheben, Teammitglieder informieren und weitere Aufgaben automatisieren. Die eigentliche Automatisierung hört sich zuerst nur nach wenigen Shellskripten an. Mit verschiedenen Schnittstellen in die Sourcecode-Verwaltung, zum Buildmanagement, Testsystem und E-Mail-Versand kommt aber schnell einiges zusammen.
|
Anstoß
Als Kohsuke Kawaguchi bei Sun an Javas XML-Schnittstellen arbeitete, war er mit den existierenden Werkzeugen nicht zufrieden und schrieb Hudson - zuerst für den Eigenbedarf. Dank seiner Plugin-Struktur und guter Community-Arbeit verbreitete sich das Tool schnell in Suns eigenen Projekten wie Java, Netbeans oder Glassfish, aber auch außerhalb von Sun. Dabei taugt Hudson nicht nur für Java-Programme, wegen seines modularen Aufbaus setzen es auch Entwickler für andere Sprachen wie C, C++, Mono oder PHP ein. Im Zuge des Aufkaufs von Sun durch Oracle verließ Kawaguchi inzwischen das Unternehmen und bietet seither auch kommerziellen Support für das von ihm entwickelte Tool an.
Hudson ist so einfach zu bedienen, dass vom Download bis zum ersten Testlauf weniger als eine Viertelstunde vergeht. Fast alle Aufgaben lassen sich mit dem intuitiven Web-GUI lösen. Wer etwas vermisst, darf auf XML-Konfigurationsdateien zugreifen oder Hudson über das Plugin-System erweitern. Weit über 300 von ihnen kennt das Werkzeug in der getesteten Version 1.355.
Kawaguchi schrieb Hudson in Java und stellt die Software als Webarchive im WAR-Format bereit. Sie lässt sich direkt mit »java -jar hudson.war« auf der Kommandozeile starten. Sie legt ihre Daten und Projekte im Ordner ».hudson« des Homeverzeichnisses des aufrufenden Hudson-Verwalters an und offeriert sein Web-GUI per HTTP auf Port 8080. Alternativ startet das Programm per
java -DHUDSON_HOME=/tmp/hudson
-jar hudson.war --httpPort=4242
mit anderen Verzeichnissen und Ports. Im Browser öffnen Anwender dann die URL »http://Server:4242/«. Hudson empfiehlt, dazu den richtigen Hostnamen an Stelle von »localhost« zu verwenden, damit auch andere Anwender erzeugte URLs nutzen können, etwa zu Fehlerreports oder Statistiken.
Ruhiger Spielaufbau
Zunächst konfiguriert der Verwalter unter »Hudson verwalten | System konfigurieren« einige Grundlagen zum Dienst, darunter Pfade zu Werkzeugen wie Shell, CVS, Java-Compiler und zum E-Mail-Server. Wer statt des ehrwürdigen CVS neuere SCM wie Git oder Subversion nutzt, der installiert oder aktualisiert unter »Hudson verwalten | Plugins verwalten« die passenden Plugins aus dem zentralen Repository oder aus lokalen Dateien. Nach einem Klick auf den Neustart-Knopf stehen sie zur Verfügung.
Hudson verwaltet auf Wunsch mehrere Benutzer, die alle individuelle Build- und Testläufe festlegen und planen dürfen. Dazu greift es über die Verwaltung des Servletcontainers auf Verzeichnisdienste wie LDAP oder Active Directory zu [4]. Dann ist jedoch ein Servletcontainer wie Tomcat, Jboss oder Glassfish angesagt. Erste Jobs lassen sich aber auch prima mit dem leichtgewichtigen Winstone-Servletcontainer über den Aufruf von »java -jar« anlegen und testen [5].
Als erster Schritt eines Anwenders ist über den Menüpunkt »Neuen Job anlegen« festzulegen, wo der Quellcode herkommt und wie sich prüfen lässt, ob er sich in einem stabilen Zustand befindet. Das nennt Hudson Job und kennt mehrere Profile, die sich besonders für Java-Anwendungen, etwa mit Maven, eignen. Die meisten Jobs sind jedoch vom Typ »Free Style«. Mit ihm lassen sich Jobs für echte Continuous Integration oder zeitgesteuerte Nightly Builds anlegen.