Kolumne: Stropek as a Service

Die Krux mit den Versionen – Warum man besser etwas mehr in richtige Versionsnummern investiert
Keine Kommentare

Wenn ich an meine ersten beruflichen Jahre in der Softwareentwicklung zurückdenke, dann waren zu dieser Zeit Versionsnummern im Wesentlichen ein Marketinginstrument. Eine große Vertriebsmesse rückt näher? Wir brauchen unbedingt einen neuen Major-Release! Man will den Kunden Stabilität vermitteln? Dann lieber einen Minor-Release herausgeben.

Wenn man ein oder zwei Mal im Jahr seine gesamte Software per DVD oder Download an die Kunden übergibt, ist diese Vorgehensweise kein Problem. Die Versionsnummer ist eigentlich nur wichtig, um rauszufinden, welche Softwareversion der Kunde betreibt, wenn er wegen eines Problems anruft. Sie hat inhaltlich keine große Aussagekraft.

Microservices statt Monolith

In Zeiten von Cloud-basiertem SaaS sieht die Sache ganz anders aus. Heutige SaaS-Lösungen bestehenden aus einer Unmenge an (Micro-)Services, die von autonomen Teams entwickelt und nach individuellen, nicht synchronisierten Rhythmen ausgerollt werden. Man muss darüber hinaus wahrscheinlich mehrere Versionen der Services gleichzeitig betreiben können, da unterschiedliche Tenants zu einem Zeitpunkt verschiedene Versionen des Softwaresystems nutzen. Es gibt auch nicht mehr eine einzelne Benutzerschnittstelle. Stattdessen greifen die unterschiedlichsten Benutzerschnittstellen (z. B. Browser, offlinefähiger Full-Client, Skills für Alexa-Integration, offizielle APIs für kundenspezifische Scripts) auf die Backend Services zu. Aus dem homogenen Softwaremonolithen von früher wurde sinnbildlich ein Sack Flöhe, der nur schwer zu hüten ist. Gute, aussagekräftige Versionsnummern sind ein wirksames Mittel, um Ordnung zu schaffen.

Versionsnamen für Marketing

Eins vorweg: Versionsnummern sind kein Marketinginstrument. Wer möchte, kann sich gerne Versionsnamen ausdenken, die in der Vermarktung einer SaaS-Lösung verwendet werden. Sie haben aber wenig mit der technischen Nummerierung von Services und Komponenten zu tun. Es ist unwahrscheinlich, dass der vom Marketing gewünschte Versionsrhythmus mit den Iterationsplänen der Entwicklungsteams übereinstimmt. Wenn man bei der Versionsnummerierung Marketing und Technik trennt, ist das kein Problem.

Ordnung durch Versionsnummern

Damit die Microservice-Teams nicht im Versionschaos versinken, braucht es klare Regeln für Versionsnummern. Es geht insbesondere um folgende Fragestellungen, auf die ich in Folge näher eingehen möchte:

  • Wie sind Versionsnummern aufgebaut?
  • Wie spezifiziert ein Client bei einem Service-Aufruf Versionen?
  • Wie definieren wir Breaking Changes und wie wirken sie sich in der Versionsnummer aus?
  • Wie werden neue Versionen and und abgekündigt?

Semantic Versioning

Ich bin ein Freund des Semantic Versionings. Dort ist festgelegt, dass Versionsnummern nach dem Schema Major.Minor.Patch aufgebaut sind. Das allein wäre aber noch zu wenig, um den Erfolg dieses Standards zu erklären. Wichtig sind die zugehörigen Regeln, die festlegen, wann Major-, Minor- und Patch-Teil der Versionsnummer zu erhöhen sind. Vereinfacht kann man sagen, dass…

  • …Breaking Changes zu einer neuen Major-Version führen.
  • …bei Minor-Versionen nur rückwärtskompatible Änderungen und Ergänzungen gemacht werden dürfen.
  • …Patch-Versionen Bug-Fixes vorbehalten sind.

Wenn ein Team klar kommuniziert, dass Versionsnummern dem Semantic Versioning folgen, vereinfacht das die Zusammenarbeit mit Service-Konsumenten erheblich. Bei einem Versionssprung von 2.1 auf 2.2 kann angenommen werden, dass Rückwärtskompatibilität gegeben ist. Falls nicht, ist das ein Bug. Bei Wechsel von Version 3.x auf 4.x weiß man, dass man besser die Release-Notes nach Breaking Changes durchsuchen sollte und mehr Zeit für Testen vorsehen sollte.

Als Konsument einer logisch zusammengehörigen Sammlung von Microservices kann es aufwendig werden, den Überblick über zueinander kompatiblen Services zu behalten. In solchen Szenarien kann es sinnvoll sein, eine Form von Gruppenversionen zu definieren. Als Aufrufer kann ich mehreren Services die gleiche Gruppenversion geben und jedes Service weiß selbst, welche eigene Version zu dieser Gruppenversion kompatibel ist. Microsoft verwendet dieses Konzept in vielen ihrer Cloud-APIs. Dabei werden Datumswerte nach dem Schema YYYY-MM-DD als Group Version Number verwendet.

Versionsauswahl

Wenn der Aufbau von und Regeln für die Vergabe von Versionsnummern festgelegt sind, stellt sich die Frage, wie ein Konsument beim Service-Aufruf festlegt, welche Service-Version er verwenden möchte. Es gibt verschiedene Möglichkeiten dafür. Hier einige Beispiele:

  1. Versionsnummer als Teil des DNS-Namen (z. B. https://v1.api.acme.com/…)
  2. Versionsnummer im Pfad (z. B. https://api.acme.com/v1.0/…)
  3. Versionsnummer im Query String (z. B. https://api.acme.com/customers?api-version=1.0)
  4. Versionsnummer im HTTP-Header
  5. Versionsnummer in der Payload von Nachrichten

Was die Beste dieser Varianten ist, lässt sich pauschal nicht sagen. Jeder Weg hat Vor- und Nachteile. Hier einige Beispiele:

  • Die Versionsnummer im DNS-Namen hat den Vorteil, dass man sehr leicht mehrere Service-Versionen parallel betreiben kann.
  • Die Versionsnummer im Query String hat den Vorteil, dass impliziert wird, dass die Struktur der Pfade von Version zu Version gleich bleibt.
  • Versionsnummern in der Nachrichten-Payload können nicht nur bei HTTP eingesetzt werden, sondern funktionieren auch bei anderen Protokollen (z. B. Message Bus, Dateien).

Man könnte einen langen Artikel nur über die Vor- und Nachteile sowie die technischen Implikationen der unterschiedlichen Konzepte schreiben. Das möchte ich an dieser Stelle gar nicht versuchen. Mir ist nur wichtig zu sagen, dass man als Unternehmen Richtlinien festlegen sollte, wann welche Herangehensweise zu wählen ist. Das beugt Missverständnissen vor und erleichtert die Kommunikation.

Es ist nicht selten zielführend, mehrere Ansätze zu kombinieren. Man könnte beispielsweise im Normalfall Versionsnummern im Query String übergeben und bei großen, strukturellen Umbauten auf eine Major-Version im Pfad oder DNS-Namen zurückgreifen. Man findet auch oft eine Kombination aus Versionsnummern im Query String und Versionsnummern in der JSON-Payload des Web-API. Ein Beispiel dafür ist Create or Update Deployment vom Azure Resource Manager. Es gibt eine Version für die Operation, das übermittelte Template (JSON) enthält jedoch zusätzliche Versionsnummern, dich sich auf das verwendete JSON-Schema beziehen.

Die Autonomie von Teams ist ein hohes Gut in der Welt von Microservices und DevOps.

Breaking Changes

Dass Breaking Changes spezifische Auswirkungen auf Versionsnummern haben sollten, wurde bereits erwähnt. Bei Web-APIs ist es aber nicht so einfach, festzulegen, was Breaking Changes eigentlich sind. Ist ein zusätzliches Feld im JSON HTTP Response Body ein Breaking Change? Was ist mit einem neuen, optionalen Parameter im Query String? Allgemeingültige Aussagen über den zu wählenden Lösungsansatz sind auch in diesem Bereich nicht möglich. Unterschiedliche Systeme können unterschiedlich strikt in ihrer Definition von Breaking Changes sein. Man sollte dem Principle of Least Astonishment folgen und das System so bauen, wie die Benutzer – im Fall von APIs sind das andere Entwickler*innen – es intuitiv erwarten. Designentscheidungen sind dadurch aber schwer zu objektivieren. In größeren Projekten (z. B. öffentliche APIs für eine große Anzahl an Konsumenten) könnte man verschiedene API-Designs durch Benutzerbefragungen oder in Fokusgruppen testen.

SLAs für Service-Versionen

Größere SaaS-Lösungen mit einer Vielzahl an Microservices entwickeln sich rasch zu einer Dependency Hell, wenn man nicht aktiv gegensteuert. Eine Maßnahme sind klare An- und Abkündigungen von Service-Versionen.

  • Neue Major-Versionen sollten idealerweise vorab zu Test- und Entwicklungszwecken zur Verfügung stehen.
  • Eine neue Major-Version eines Service mit Breaking Changes sollte die Vorgängerversion nicht ersetzen. Für eine gewisse Zeit sollten beide Versionen zur Verfügung stehen, um die Inbetriebnahme einer neuen Service-Version von der Inbetriebnahme neuer Versionen der Service-Konsumenten zeitlich zu entkoppeln.
  • Wenn eine neue Major-Version eines Service angeboten wird, sollte klar kommuniziert werden, wie lange ältere Service-Versionen noch angeboten werden.

Enterprise Alignment vs. Autonomie

Die Autonomie von Teams ist ein hohes Gut in der Welt von Microservices und DevOps. Meiner Ansicht nach sollten SaaS-Anbieter zentrale Regelungen auf ein Minimum reduzieren und den Teams möglichst hohe Freiheit einräumen. Wie auch in der physischen Welt braucht es aber allgemeingültige Regelungen, wenn es um die Zusammenarbeit von Teams geht. Für mich gehören grundlegende Richtlinien bezüglich Versionsnummerierung zu den Bereichen, die nicht den Microservice-Teams überlassen werden sollte. Es braucht einen Mindeststandard, auf den sich alle verlassen können und der nicht in jeder API-Spezifikation erneut gefordert werden muss. Für Entwickler und Konsumenten eines API müssen die Annahmen und Anforderungen klar sein.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -