Mittwoch, 28. September 2011

Lieferumfang

Wenn es darum geht, eine entwickelte Software auszuliefern, gibt es zwei Extreme: Eine Lieferung der kompletten (virtuellen) Appliance, am besten versiegelt, und eine Lieferung von nackten Komponenten mit Handbuch. Die Realität ist irgendwo dazwischen: Die Appliance ist sicherlich ein für Hersteller und Support attraktiv, verbietet sich aber oft durch Probleme bei der Integration in bestehende Infrastruktur, und nackte Komponenten sind nicht unbedingt das, was Kunden kaufen wollen.

Hierzu eine Anmerkung: Der Lieferumfang eines Produktes sollte immer so strikt wie möglich definiert sein, also nur die absolut notwendigen Bestandteile umfassen. Beispiel: Wenn ich eine Web-Applikation liefere, dann enthält mein Lieferpaket im Idealfall nur die unvermeidlichen Bestandteile meine-webapp.war und Handbuch-für-meine-webapp.pdf, in dem steht, auf welcher Plattform meine-webapp.war deployed werden kann.

Warum? Weil man für alles, was man liefert, verantwortlich ist. Im schlimmsten Falle also für jeden Programmfehler im verwendeten Tomcat, sofern man sich erweichen ließ und einen Tomcat ins Lieferarchiv gepackt hat. In diesem Falle muß man also regelmäßig Updates der ursprünglichen Lieferung schicken, die alle getestet werden müssen -- und obwohl die eigene Kreation sich möglicherweise schon lange nicht mehr geändert hat, entsteht hier ein regelmäßiger Aufwand. Ist man mit den Verträgen ungeschickt, sind womöglich Probleme mit der Gewährleistung nicht ausgeschlossen. Schön, das ist ein Schreckensszenario, welches so schnell nicht eintreten sollte, aber es bleibt ein potentielles Problem.

Das hat auch eine Auswirkung auf die Softwareentwicklung: Der Verzicht auf das "Anpassen" (aka "customizing") der Plattform vereinfachen Deployment und Betrieb und erlaubt, die Plattform "out-of-the-box" zu verwenden. Damit entfällt ein wichtiger Grund, die Plattform mitzuliefern, den Lieferumfang deutlich strafft.

Dienstag, 20. September 2011

Über Keyword Substitution

Mal wieder Git, aber diesmal ein Thema, was Git nicht kann: Keyword Substitution. Wer RSC, CVS oder SVN kennt, ist früher oder später über die praktischen kleinen Helferchen gestolpert, die in jede Datei die Versionsnummer fest einbrennen, und auch ältere SCM-Fossile verfügen über diese Fähigkeit. Ich selbst habe in meiner Zeit als CVS-Anwender in jeden Dateiheader sklavisch ein $Id$ gehackt und das gleich zur persönlichen Best Practice erklärt, denn schließlich ist es ja wichtig, jederzeit zu wissen, in welcher Dateiversion man unterwegs ist. Daher hat es mich etwas verstört, daß Git nicht nur keine Keyword Substitution kennt, sondern die Git-Entwickler sich auch noch strikt weigern, eine solche einzubauen. Was denken die sich dabei?

Wie sich herausstellt, haben sie gute Gründe -- am einfachsten von Linus Torvalds in einer ausreichend undiplomatischen eMail zusammengefaßt. Die Argumente im einzelnen:

Zunächst einmal ist klar, daß externe Tools von $Id$-Strings verwirrt werden, schließlich haben die keine Möglichkeit, die zu vergleichenden Texte ohne die Substitution zu vergleichen. Aber das ist vielleicht nicht so schlimm, denn erstens kann man ja alle zu vergleichenden Texte vorher durch einen Filter schicken, der die Strings entfernt -- genau so wie es CVS und SVN beim Einchecken tun.

Der zweite Punkt leuchtet auch sofort ein: Ein SCM, welches eine Keyword Substitution vornimmt, muß genau wissen, was man gerade eincheckt. Warum ist das ein Problem? Wir wissen ja schließlich auch, daß man Binärdateien nicht mergen kann, und schrecken trotzdem nicht vor dem Mergen zurück! Der Grund liegt in der Art, wie ein SCM Dateien mit Keywords speichern muss: Nämlich erstaunlicherweise ohne Keywords! Die Keywords werden tatsächlich während des Auscheckens ersetzt, da ansonsten zwei Versionen eines Textes garantiert unterschiedlich wären, selbst wenn sich inhaltlich nichts geändert hat. Irrt sich jetzt das SCM beim Einchecken, so zerstört es die zu sichernde Datei und speichert einen großen Haufen Müll, was im schlimmsten Falle erstmal niemanden auffällt (unbedingt mal ausprobieren: Ein PDF in VSS einchecken -- wird als 7-Bit-EBCDIC-Text erkannt und rettungslos verstümmelt). Dem Nutzer wird das erst bewußt, wenn er mal Dateien aus dem SCM abrufen will. Aber dann sind seine vorherigen Bemühungen bereits zerstört.

Der dritte Punkt klingt erstmal etwas altklug: Natürlich weiß das SCM viel besser, welche Version ich gerade ausgecheckt habe, aber ich will das doch auch sehen! Nun, tatsächlich kann ich das ja auch sehen, aber die Frage ist: Wann muß ich es wissen? Nicht beim Schreiben von Code, denn da arbeitet man ohnehin auf dem HEAD. Interessant wird die Version einer Datei bei der Analyse von Code, und hier spielt die Version einer einzelnen Datei eine verblüffend geringe Rolle. Wichtiger ist hier der Kontext: Welche Dateien gehören zusammen, welche Änderungen bilden einen inhaltlich zusammengehörigen Change Set? An dieser Stelle klickt wieder ein Puzzleteil an die richtige Stelle: Git hat ohnehin keine handlichen Versionsnummern, nur SHA1-Identifier für Change Sets, und die vermißt wirklich niemand im Quelltextheader.

Nun, vielleicht nicht im Quelltextheader, aber wie ist es mit der "About this Application"-Box? Ah, richtig, die ausgelieferten Versionen müssen natürlich irgendwie kenntlich gemacht werden. Aber hier kommt ein anderes Prinzip zum Tragen: Die Produktversion hat nichts mit der technischen Version des SCM zu tun. Wirklich nicht. Und wenn die Produktversion nicht von der SCM-Version abhängt, muß die SCM-Version auch nicht im Produkt stehen. Hier bieten sich Build-Nummern an, die ihrerseits Tags im SCM steuern (das SCM ist also nicht das führende System).

Zuletzt aber noch ein Argument, für das ich im Moment kein Zitat finde (auch das ist von Torvalds, nur beweisen kann ich's nicht): Ein SCM muß Dateien immer unverändert speichern, und wenn sich zwei Versionen einer Datei nur in der Versionsnummer unterscheiden, hat das SCM einen fundamentalen Fehler. Warum? Weil ein SCM schließlich Inhalte speichern muß und nicht einfach nur Nummern hochzählt (das können Taschenrechner besser). Folglich muß ein funktionierendes SCM zwei Dateien, die sich nicht unterscheiden, immer die selbe Versionsnummer zuweisen.

An dieser Stelle muß man erstmal kurz anhalten und ausführlich nachdenken. Es stimmt, natürlich, und es hat Konsequenzen: Demnach sind nicht nur die Keyword Substitutions schlecht, sondern auch alle automatischen Umkodierungen (Unix/DOS, ASCII/UTF-8, ...). Und wer schon ein Weilchen mit verschiedenen Plattformen und SCMs zu tun hatte, weiß, wie viele Probleme sich mit dieser Regel in Luft auflösen.


P.S.: Ich bin sehr froh, recht schnell eingesehen zu haben, daß Torvalds Recht hat. Ich wäre nicht gerne Anhänger einer furchtbaren Idee, noch dazu idiotisch, welche seit Dekaden fundamental fehlgeleitete SCM-Designs bestimmte. Denn ich habe das Licht gesehen. Leider muß ich jetzt zurück in den Keller zu SVN.