Freitag, 27. Mai 2011

Continuous Integration: Hudson

Brown Field Projekte sind oft in einem schlechten Zustand, oft wissen die Beteiligten gar nicht wie es um ein Projekt steht, oft haben sie nur eine Ahnung oder ein Gefühl. Um Brown Field Projekte unter Kontrolle zu bringen und Wartbarkeit, Qualität und Sicherheit zu erhöhen wird bei Brown Field Projekten als eine der ersten Massnahmen Continuous Integration (CI) etabliert. Zurzeit sind eine Reihe von CI-Systemen verfügbar. Dazu zählen die populären Systeme:
Alle drei Systeme eignen sich für Java-Projekte, sind aber offen und flexibel auch andere Programmiersprachen zu unterstützen. Der prinzipille Ablauf ist folgender:
  • Auschecken des Projektes aus der Codeverwaltung (CVS, SVN)
  • Build des Projektes (Maven, ANT)
  • Benachrichtung von Benutzern über das Ergebnis (Email)
In den Klammern hinter den Schritten stehen die populärsten Vertreter für diese Schritte. Sie werden in der Regel von allen CI-Systemen unterstützt. Oft unterstützen die CI-Systeme auch noch andere Systeme.

Continuum 1.3.7
Auf meinem Testrechner lief ein aktuelles Windows 7. Continuum ist sowohl aus Webapp für Tomcat als auch als Standalone-Version verfügbar. Letztere probierte ich zu installieren und zu benutzen. Leider liess sich Continuum nicht starten und eine Beschreibung war nicht zu finden. Das ist das AUS für Contiunuum. Continuum macht sonst den Eindruck sehr stark auf Maven zu fokussieren, also ist Continuum ein Tipp für alle Maven Benutzer.


Hudson 2.0
Auf meinem virtuelle Testrechner lief ein Fedora 14 Linux. Zusätzlich habe ich JAVA, ANT und Maven2 installiert. Leider ist keiner der CI-Systeme per YUM zu installieren. Schade, doch Hudson lies sich einfach von der Website über einen Link aus installieren. Das funktionierte sehr gut. Auch bei Hudson entschied ich mich für die Standalone-Variante. Nach der Installation lief Hudson schon als Demon, nur leider funktionierte Hudson nicht ganz, die Weboberfläche (http://localhost:8080) war da, liess sich aber nicht benutzen. Nach einem manuellen Start von Hudson als Root funktionierte alles.
/etc/init.d/hudson stop
java -jar /usr/lib/hudson/hudson.war
Strg+C
/etc/init.d/hudson start
Ich konnte Jobs einrichten und abarbeiten. Für den Zugriff aus CVS musst ich das Passwort und den Benutzernamen in Feld CVSROOT eingeben. Je nach dem wer (Root oder User) und wie (Demon oder Terminal) Hudson gestartet wird legt Hudson eine Verzeichnisstruktur an verschieden Orten auf dem Volume an. Also nicht erschrecken, wenn ihr Hudson als User startet und nicht die Jobs seht, die ihr vorhin angelegt habt, wahrscheinlich lief Hudsun da als Demon, also Huson beenden und als Demon neu starten. Dann ist alles wieder OK.
Zur CVS Integration kann Hudson auch die Datei .cvspass benutzen, das funktioniert aber nur eingeschränkt. So kann Hudson als Demon gestartet trotz richtiger Dateirechte nicht auf die .cvspass eines Benutzers zugreifen.
Ein schönes Feature ist auch die Möglichkeit von Hudson Programme wie ANT oder Maven selbständig aus dem Internet zu laden und sogar in verschiedenen Versionen dem Benutzer anzubieten. Auch wenn Fedora über ein aktuelles ANT verfügt ist es trotzdem zu empfehlen, das ANT via Hudson zu installieren, die erhöht die Konsistenz in der Softwareentwicklung und elemeniert ein potentielle Fehlerquelle, unterschiedliche ANT oder Maven Versionen.
Trotz dieser Hürden schien Hudson gut zu funktionieren, bis ich versuchte die Plugins zu aktualisieren. Dabei wurde meine Hudson Installation so beschädigt, dass Hudson nicht mehr zum Arbeiten zu überreden war. Schade.
Trotz dieser hidden Features ist Hudson zu empfehlen.

Sonntag, 15. Mai 2011

Java Performance Tipp Nummer 1

Die einfachste Möglichkeit die Geschwindigkeit von Java-Anwendungen zu erhöhen besteht darin, die aktuelle JVM zu verwenden. Es gibt einen deutlichen Performanceunterschied zwischen den zur Zeit gebräuchlichen Java-Versionen. Leider sind meine Bio-Benchmarkergebnisse (DNA Alignment) nicht mehr existent aber unter folgenden Links sind ähnliche Tests und Aussagen zu finden. Java 7 ist schneller als Java 6. Java 6 ist schneller als Java 5. Die Unterschiede sind größer als 10%, d.h. ein Update auf die aktuelle Java-Version lohnt sich auf jeden Fall.

Samstag, 14. Mai 2011

Codeoptimierung: Wurzel allen Übels

Das erste mit dem Softwareentwickler in Projekten anfangen, ist die Optimierung ihres Codes. Wahrscheinlich dient dies als Beweis ihres Könnens. Klar, Optimierungen sind sind immer ein Fall für erfahrenen Entwickler. Aus diesem Grund ist dieses Streben nach optimiertem Code von Beginn an verständlich. Nur was nützt schneller (dazu kommen wir in einem andern Post) Code der schnell Fehler produziert aber nicht die gewünschte Funktion? Durch die aufwendige Fehlersuche und Fehlerbehebung kostet das oben beschriebene Vorgehen mehr Entwicklungszeit im Vergleich zum normalen Entwickeln. Was lernen wir daraus, Optimierungen sind prima, wenn man sie nicht macht.

The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson

Aus agiler Entwicklungssicht sind Optimierungen erst notwendig, wenn sie notwendig sind. Optimierungen sind Teil des Refactoringprozesses in der agilen Softwareentwicklung. Wichtiger ist die Verständlichkeit und die Wartbarkeit des Codes. Aber zurück zur Optimierung, der erste Schritt bei der Optimierung ist es, festzustellen das es ein Problem gibt, dass durch Optimierung gelöst werden kann, der zweite Schritt ist es das entsprechende Verhalten der Software zu dokumentieren und ein Testset aufzubauen mit dem die Ergebnisse nachvollziehbar sind. Im dritten Schritt wird das Problem analysiert (Profiling) und die beste Stelle (Bottleneck) zur Optimierung gefunden. Erst im vierten Schritt wird der Code optimiert. Dann wird der Effekt der Optimierung mittels des Testsets dokumentiert (fünfter Schritt). Die Optimierung von Code besteht aus folgenden Schritten:

  1. Feststellen und Dokumentieren das es ein Problem gibt.
  2. Definieren eines Testsets und Dokumentieren der Ergebnisse für den nichtoptimierten Code.
  3. Analyse des Problems z.B. mittels Profilings und finden der Codestelle für die Optimierung.
  4. Optimieren des Codes.
  5. Dokumentation der Ergebnisse des optimierten Codes mit Hilfe des Testsets.

Und eins sollte man nie vergessen, die Entwicklungszeit die in eine Optimierung fliesst, muss durch den Optimierungsgewinn gerechtfertigt sein.