“Evil SNAPSHOTs”

Warum keine Snapshots verwendet werden sollten

13. März 2014Dr. Halil-Cem Gürsoy

Die “klassische” Softwareentwicklung teilt ein Projekt in viele verschiedene Phasen auf. Dort existiert beispielsweise eine Phase, in der Anforderungen aufgenommen werden, eine Phase, in der die Software implementiert wird, gefolgt von einer, in der diese intensiven Tests unterzogen wird. All diese einzelnen Schritte dienen dazu, die Software bereitzustellen. Auch dieser “Bereitstellung” (Release) ist eine eigene Phase gewidmet (s. B. Boehm, Software Engineering Economics, Prentice Hall, 1981). Dies bedeutet, dass die Software erst zum Ende des “Wasserfalls” bereitgestellt werden muss. Bis zu diesem Punkt ist die Entwicklung im Fluss und die Software liegt in Entwicklerversionen vor.

Auch in anderen Vorgehensmodellen wie Scrum1 – ich nenne sie einmal provokativ “semi-agil” – liegen solche Phasen implizit vor. Hier sind sie allerdings eingebettet in recht kurze Iterationen (“Sprints”) von wenigen Wochen und Ziel ist es, zum Ende eines solchen Sprints ein Stück Software auszuliefern, das zum Beispiel einem Stakeholder bereits zur Verfügung gestellt oder in eine Produktionsumgebung überführt werden kann. Innerhalb des Sprints haben wir es wiederum mit Entwicklerversionen zu tun. Diese Entwicklerversionen werden allgemein gebräuchlich “Snapshot” (“Zwischenstand”) genannt.

Im Kontrast zu diesen Vorgehensmodellen steht das Konzept “Continuous Delivery”2. Hierbei wird ausdrücklich auf das erste Prinzip des Agilen Manifestes Bezug genommen:

 

“Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.”

 

Dies bedeutet, dass, streng nach dem Agilen Manifest, ein Projekt in der Lage sein sollte, zu jeder Zeit getestete, lauffähige und wertvolle Software auszuliefern.

Einer der wichtigsten Grundsätze in diesem Verfahren lautet: Wird ein Binärartefakt erzeugt, darf dieses nicht mehr verändert werden. Dieses Artefakt durchläuft, wenn alles gut geht, unverändert alle Stages des Entwicklungs- und Release-Prozesses (z.B. UAT, Capacity testing usw.) in einer Deployment Pipeline und wird am Ende in die Produktion überführt. Dabei liegt zu Beginn mit jedem gebauten Artefakt ein “Release Candidate” vor. Abhängig von der Qualität dieses Artefaktes und der Vollständigkeit der Features kann dieses nun von einem einfachen “Release Candidate” zu einem „Release“ befördert werden (“Artifact promotion”). Dies verdeutlicht sich durch das absolvieren der einzelnen Stages. Diese „Beförderung“ ist auch als Freigabe zu verstehen und geht mit dem Durchlaufen der Stages einher. Technisch kann ein Artefakt durch verschiedene Verfahren befördert werden: Man kann es in den  Metadaten eines Artefaktes in einem Repository Server kenntlich machen oder auch schlicht durch das Verschieben eines Artefaktes aus einem “Release Candidate Repository” in ein “Releases Repository”3.

SNAPSHOTS hingegen stehen diametral zu diesem Verfahren. In klassischen Verfahren müsste, nachdem alle Tests erfolgreich durchgeführt wurden und bevor diese Version des Projektes in die (Pre-) Produktion überführt wird, das Artefakt erneut als Release gebaut werden. Neben dem Problem, dass nun ein Projektstand ein zweites Mal gebaut wird, ist häufig zu beobachten, dass genau diese Release-Version ungetestet direkt in die (Pre-)Produktion überführt wird.

Diese klassischen Vorgehensmodelle manifestieren sich auch in Build-Werkzeugen wie Apache Maven. Hier wird in der Versionsangabe eines Projektes oder Moduls zwischen einer Entwicklerversion und einer Auslieferungsversion unterschieden. Erstere hat den so genannten “SNAPSHOT”-Qualifier. Das bedeutet, die Versionsbezeichnung für ein Produkt in der Entwicklung hin zur Version „1.0.0“ sieht so aus: “1.0.0-SNAPSHOT”. Der Auslieferungsversion fehlt dagegen dieser Qualifier.

Möchte nun ein Team, welches Apache Maven verwendet, eine Auslieferungsversion (“Release”) erstellen, so greift diese in der Regel auf ein Plugin Namens “Maven Release Plugin” zu. Dieses Werkzeug versucht nun, in der zugrunde liegenden Versionsverwaltung einen “Label” zu setzen, die Version des Projektes in der Projektdefinition (POM) anzupassen etc. Insgesamt sind in diesem Prozess drei Compile-/Test-Schritte, zwei POM-Transformationen sowie drei Revisionen in der Versionsverwaltung involviert. Dieser Prozess muss vor jeder Auslieferung durchgeführt werden und ist leider recht fehleranfällig.

Ganz unabhängig davon, welches Vorgehensmodell zugrunde liegt: das wiederholte Bauen und Testen eines Projektstandes ist eine Verschwendung von Ressourcen. Zudem eröffnet sich bei näherer Betrachtung ein weiteres Problem, dass häufig leider eher als Vorteil bewertet wird: Snapshots in der Abhängigkeitsverwaltung.

In einer idealen Projekt- und Entwicklerwelt mit vielen voneinander abhängigen Modulen sichert die Verwendung von Snapshot-Abhängigkeiten, dass immer die aktuellste Version eines Moduls verwendet wird:

Was passiert aber, wenn diese Snapshot-Abhängigkeiten ab und an defekt sind? Letztendlich kann dies dazu führen, dass der Build über einen längeren Zeitraum hinweg instabil ist und nicht erfolgreich duchgeführt werden kann. Ist es mal nicht die eine Komponente, ist es eine andere, die Probleme bereitet. Viel sinnvoller wäre es, wenn Abhängigkeiten zu Versionen bestehen, die von dem jeweiligen Komponententeam als “stabil” erachtet wurden und eine entsprechende “Beförderung” erfahren haben.

Der Verzicht auf die Verwendung von Snapshot-Versionen kann in einem Maven-Projekt mit einfachen Mitteln erreicht werden. Das Grundgerüst stellt “Versions Maven Plugin” bereit, mit dessen Hilfe eine Version in einer Maven-POM-Datei überschrieben werden kann.

In der POM-Datei kann dabei noch eine beliebige Versionsbezeichnung stehen, wie zum Beispiel:

Wird der Build lokal auf einem Entwicklerrechner durchgeführt, so wird auch tatsächlich diese Version 1.0.5-SNAPSHOT gebaut. Da ein Maven Deploy in ein zentrales Repository aus einem Entwicklerrechner heraus tunlichst zu unterlassen ist, ist dies nicht weiter schmerzlich: das Artefakt liegt, wenn überhaupt, nur in dessen lokalem Repository.

Wird nun das Projekt in der zentralen Build-Umgebung gebaut, z.B. mit Hilfe des CI-Servers Jenkins, soll das Artefakt eine eindeutige Versionsnummer erhalten. Ein Aufruf des Versions Maven Plugins im Rahmen des Build Jobs mit

würde zu einer Version wie “478-1068” führen.

Dieses Verfahren kann weiter ausgebaut werden, beispielsweise kann dafür gesorgt werden, dass die ursprüngliche Versionssemantik erhalten bleibt, so dass eindeutige Versionsbezeichnungen wie “1.0.5-478-1068” erhalten werden4.

Letztendlich besteht keine Notwendigkeit, weiterhin Snapshots zu verwenden. Vielmehr bringt die Verwendung dieser neben redundanter Prozessschritte auch Risiken bezüglich der Build-Stabilität mit sich.

Habe ich Ihr Interesse zu diesem Thema geweckt? Dann schauen Sie doch auf den diesjährigen Berlin Expert Days am 3. und 4. April vorbei und besuchen Sie diese Talks:

  1. Quelle: M. Beedle, K. Schwaber, Agile Software Development with Scrum, Prentice Hall, 2002
  2. Quelle: J. Humble, D. Farley, Continuous Delivery: Reliable Software Releases Through Build, Test, and Deployment Automation, Addison-Wesley Longman 2010
  3. Quelle: Auch wenn einige Autoren wie z.B. in http://www.stephen-smith.co.uk/pipeline-antipattern-mutable-binary-location/ dieses Verfahren als Anti-Pattern bezeichnen ist dieses doch recht häufig aufgrund des sauberen Trennung von Produktiven von Nicht-Produktiven Artefakten beliebt.
  4. Quelle: Eine Beispiel-POM zur Verwendung in einer Deployment Pipeline in Jenkins findet sich dazu unter https://github.com/hcguersoy/angularjs-springmvc-example/blob/master/angularjs-springmvc/pom.xml
Dr. Halil-Cem Gürsoy Dr. Halil-Cem Gürsoy ist als Principle Software Architect bei adesso tätig. Sein technologischer Schwerpunkt liegt dabei auf Java Enterprise. In diesem Kontext konzentriert er sich auf verteilte Systeme, Cloud-Architekturen sowie Build- und Deployment-Prozesse in verteilten Systemen.
Artikel bewerten:
1 Star2 Stars3 Stars4 Stars5 Stars
Loading...

Kommentar hinzufügen:

Ihr Kommentar: