Warum Optionals nicht serialisierbar sind

Im Java Magazin vom Juli 2017 wurde im Artikel über das Projekt „vavr“ die Klasse „Option“ erwähnt, die die Java-8-Optionals ergänzt und – hurra – serialisierbar ist. Warum ist „Optional“ selbst eigentlich nicht serialisierbar?

Zunächst einmal ist Optional als Monade keine Datenstruktur, sondern ein Container der eine Verarbeitung repräsentiert. Ähnlich einem Java-Stream der dazu dient Mengen von Objekten zu verarbeiten, aber nicht zu speichern. So ist der Stream nach Gebrauch verbraucht und nicht mehr zu verwenden, für die nächste Verarbeitung muß ein neuer her.

Oder anders ausgedrückt: Das Bierfaß bleibt in den Keller, nicht der Rollkutscher der es gebracht hat… Zum anderen ist da das Ding mit null. Optionals sollen es ja ermöglichen, daß man null-Werte in gleicher Weise verarbeiten kann wie „richtige“ Objekte die nicht null sind. Bei der Deserialisierung muß man das beachten und gegebenenfalls auf das Fehlen des Objekts reagieren. Aus Java-Sicht ist aber auch Optional ein Objekt und kann „null“ sein; bei der Deserialisierung hat man also nichts gewonnen, sondern muß neben dem Fall „Optional enthält null“ eben auch den Fall „Optional ist null“ berücksichtigen. Also besser ohne Optional einpacken und beim Auspacken gleich in ein Optional stecken.

Aus dem gleichen Grund übergibt man Optionals normalerweise auch nicht als Parameter an Methoden. Funktionen die Optionals als Ergebnis liefern sind hingegen ok – wer allerdings eine solche Methode mit dem Ergebnis „null“ verenden läßt, sollte besser den Job wechseln…

Die Mär vom Zero Turnaround

In seinem Buch „Psychology of Computer Programming“ schreibt Gerald Weinberg 1971 über verschiedene Untersuchungung zur optimalen Länge der Turnaround-Zeit, also die Zeit die vergeht zwischen der durchgeführten Programm-Änderung und dem Feedback das der Programmierer über die Auswirkungen erhält. In jenen Tagen meinte das die Zeit zwischen der Abgabe des Lochkarten-Stapels beim mainframe-Operator und der Abholung des Ausdrucks mit dem Ergebnis.

Allein die Tatsache, daß die Untersuchungen kein einheitliches Ergebnisse erbrachten muß den Programmierer von heute überraschen. Warum sollte man etwas anderes erwarten als den Wunsch nach unmittelbarem Feedback? Tatsächlich gab es schon damals Manager, die genau diese Erwartung hatten. Eine Befragung brachte das erstaunliche Ergebnis, daß ein Durchschnittlicher Tunaround von 31 Minuten als zu kurz empfunden wurde. Was soll man davon halten?

Ergänzend dazu sollte vielleicht erwähnt werden, daß in jener Zeit die Time-Sharing-Systeme aufkamen, die es dem Entwickler ermöglichten die Programm-Aufträge direkt am Terminal aufzugeben und das Ergebnis abzuwarten. Anders als heute waren sich die Entwickler erstaunlicherweise noch nicht einig, ob das Dialog- dem Batch-System vorzuziehen sei.

Unvorstellbare Ansichten? Wer heute einen Computer befragt, erwartet Antwort in Echtzeit, möglichst ohne erkennbaren Verzug — schließlich will man so schnell wir möglich weiterarbeiten. Aber es wäre doch absurd annehmen zu wollen, daß der Batch-Entwickler nach Abgabe seines Lochkartenstapels die halbe Stunde däumchendrehend auf seine Kaffeetasse gestarrt hätte. Nein,, er hat vielmehr die Wartezeit damit genutzt über sein Programm nachzudenken, die nächsten Schritte zu planen, das Ziel des nächsten Probelaufs vorzubereiten. Die Auszeit gab Gelegenheit die Augen vom unmittelbaren Problem zu lösen und den Blick über die gesamte Aufgabe schweifen zu lassen.

Die lange Wartezeit erhöhte aber auch die Wertschätzung des Entwicklers für den Testlauf. Um diesen nicht durch einen Flüchtigkeitsfehler zu unbrauchbar zu machen, haben die Entwickler mehr Sorgfalt auf die Programmierung verwandt. Wir sind heute gewöhnt, daß uns die IDE unsere Syntax-Fehler beim Eintippen sofort um die Ohren haut. Wer zwischendurch auch mal mit dem klassischen Edit – compile – run – Zyklus arbeitet, kennt den Unterschied.

Was können wir davon für die heutige Entwicklungsarbeit mitnehmen? Wartezeit ist keine verlorene Zeit wenn man sich nutzt. Schrumpft die Turnaround-Zeit auf Sekundenbruchteile zusammen läßt sie sich nicht mehr nutzen, ist also tatsächlich verloren. Der geneigte Leser mag selbst mal zusammenrechnen — und darüber staunen — was ihm da über den Tag verloren geht.

Und auch an die Wertschätzung sollten wir im immer schneller rotierenden Wirbel des TDD-Zyklus denken. Je kleiner die Änderungen im Zyklus werden, desto größer wird die Gefahr daß der Entwickler den Blick für das Gesamtproblem verliert. Das klingt abstrakt und paranoid; es soll auch nicht bedeuten, daß jeder Entwickler zwangsläufig in solchen Arbeitsstil verfällt. Ich möchte es verstanden wissen als Einladung sich selbst beim Arbeiten zuzuschauen und mal zu reflektieren, welche Auswirkungen die Arbeitsweise hat.

Ich stecke während der Leerlaufzeiten immer gern den Kopf aus dem Maschinenraum. Ist die turnarount-Zeit zu lang, kommt das Boot nicht vorwärts. Ist sie zu kurz, wird es vom Kurs abkommen.

Sprache und Qualität

Was hat Sprache mit Qualität zu tun? Was hat sie insbesondere mit Code-Qualität zu tun? Bei der (natürlichen) Sprache geht es — wie beim Code — nicht nur darum, einen Sachverhalt irgendwie auszudrücken. Es gilt, ihn so auszudrücken, daß er seien Zweck möglichst gut erfüllt. Selten geht es darum, einfach nur Information zu übermitteln, man will auch überzeugen, beeindrucken, Gefühle beim Leser wecken. Und selbst wenn es tatsächlich nur um die Information geht, wird es nötig sein, die Formulierung dem Ziel-Publikum anzupassen. Ein Text kann also einen Zweck mit mehr oder weniger Qualität zu erfüllen trachten.

Daß man von Computer-Sprachen spricht, ist mehr als eine zufällige Homonymie. Zwar geht es in erster Linie darum, einen Sachverhalt exakt und eindeutig darzulegen, aber je nach dem welche Konstrukte man für die Implementierung wählt ist das Ergebnis für den Menschen mehr oder weniger verständlich. Warum ist das wichtig? Die Maschine interessiert sich nicht dafür wie das Programm aussieht, sie führt aus was ihr gegeben wird. Beim Programmierer ist das anders

Code wird für Computer geschrieben, aber für Menschen formuliert

So sinnvoll es im Umgang mit natürlicher Sprache ist über die geeignete Formulierung nachzudenken, so sinnvoll ist es, beim Formulieren von Computer-Code über die zukünftigen Leser nachzudenken. Wie Robert C. Martin ganz richtig festgestellt hat, verbringt der Programmierer wesentlich mehr Zeit damit Code zu lesen — und zu verstehen — als damit ihn zu schreiben.

Ein anderer Aspekt der natürlichen Sprachen ist nicht so einfach auf die Computer-Sprachen zu übertragen:

Die Grenzen meiner Sprache bedeuten die Grenzen meiner Welt.

„Ludwig Wittgenstein“

Computer-Sprachen sind in der Regel Turing-vollständig. In jeder (vollständigen) Computer-Sprache läßt sich alles formulieren, was sich mit einer Turing-Maschine berechnen läßt und umgekehrt. Das heißt, daß alle Computer-Sprachen — ihren theoretischen Möglichkeiten nach – gleichmächtig sind; keine „kann mehr“ als irgendeine andere. Inwiefern begrenzt aber dann die Sprache die Welt des Programmierers?

Wer schon einmal versucht hat auch nur eine Addition mit einer Turing-Maschine zu berechnen, weiß was für eine enormer Unterschied zwischen Computer-Sprachen besteht. Nutzt man zur Lösung eines Problems eine Sprache die dafür geschaffen oder gar daraufhin optimiert wurde, sehen die Programme ganz anders aus. Der Code ist kompakter, leichter zu lesen und schneller zu verstehen, umfangreichere Probleme lassen sich damit lösen.

Das soll uns aber nicht in falsche Sicherheit wiegen. In jeder Sprache lassen sich unverständliche Programme schreiben. Ich jedenfalls kenne keine Sprache die das unmöglich macht. Man kann unter „Sprache“ auch die Art und Weise verstehen, wie man die Sprache einsetzt: Spreche ich „sauberes“ Deutsch oder bin ich nachlässig in Grammatik und Ausdruck? Wähle ich die passenden Worte oder einfach Worte die eben nur „ungefähr“ das ausdrücken was ich zu denken glaube?

Schlecht formulierter Code ist nicht nur schlecht zu verstehen. Er ist in der Regel auch schlecht zu ändern und zu erweitern. Schlechte, schlampige Sprache –- im Sinne der Verwendung -– schränkt den Programmierer ein; die Sprache — bzw. die Verwendung derselben — bestimmt die Welt des Programms.

Je mehr Sorgfalt man in die Formulierung legt, desto höher die Qualität des Textes — oder des Codes. Die Beschäftigung mit Sprache — ob natürlich oder künstlich — ist für den qualitätsorientierten Entwickler eine Notwendigkeit.

Über Metriken

Immer mal wieder bin ich in eine Diskussion über Metriken für Code-Qualität geraten in deren Verlauf ich mich gefragt habe, ob meine Vorstellung vom Begriff „Metrik“ eigentlich richtig ist. Um nicht jedesmal wieder zweifeln zu müssen, habe ich versucht das zu formulieren.

Als Metrik bezeichnet man in der Mathematik eine Funktion, die den Abstand zweier Punkt eines Raum (oder einer Menge von Objekten) berechnet. Unter „Abstand“ versteht man hier einen nicht negativen (reelen) Wert oder lax ausgedrückt: eine positve Zahl die auch null sein kann. Nicht jede solche Funktion ist tatsächlich eine Metrik, sie muß noch einige Bedingungen erfüllen, die hier nachzulesen sind. Für die Metriken in der Qualitätsbestimmung sind diese aber erstmal nicht von Interesse.

Die Definition nach IEEE 1061 wird üblicherweise so wiedergegeben:

Eine Software-Qualitätsmetrik ist eine Funktion, die eine Software-Einheit in einen Zahlenwert abbildet, welcher als Erfüllungsgrad einer Qualitätseigenschaft der Software-Einheit interpretierbar ist.

Sie ist also — wie ihre mathematische Schwester — eine Funktion, die Objekten — hier sind es Software-Einheiten, oder „software data“ wie es im englischen Äquivalent heißt — Zahlenwerte zuweist.

Die Software-Metrik weist also beliebigen Software-Bestandteilen Zahlen zu. Ist die „Software-Einheit“ ein Stück Code — betrachten wir im weiteren an diser Stelle Java-Klassen — dann können wir mithilfe der Metrik jeder Java-Klasse eine Zahl zuordnen. Und weil Zahlen im Gegensatz zu Java-Klassen eine natürliche Ordnung besitzen, kann man sie sinnvoll mit einander vergleichen. Überträgt man die Zahlen-Werte auf die Java-Klassen kann man nun die Java-Klassen miteinander vergleichen.

Wenn die Metrik zum Beispiel „Anzahl der Methoden“ heißt, kann man nun sagen: ist die Zahl der Methoden in Klasse A größer als die der Methoden in Klasse B, dann kann man — analog dazu — sagen: Klasse A ist größer als Klasse B. Statt „größer“ kann man auch ein anderes quantifizierbares Attibut verwenden: besser, schlechter, schöner, häßlicher,…

Aber genau mit diesem letzten Schritt haben wir den Definitions-Bereich der Metrik verlassen. Die Metrik ist eben nichts weiter als die Funktion und wenn man so will die Ordnung die sie definiert; sie hat nichts mit ihrer Interpretation zu tun. Wenn man daher sagt: Klasse A ist besser als Klasse B weil für Metrik x gilt: x(A) > x(B) dann „interpretieren wir sie als Erfüllungsgrad einer Qualitätseigenschaft“ um mit der IEEE-Definition zu sprechen. Das gleiche gilt, wenn verlangt wird daß ein bestimmter Schwellwert über- oder unterboten werden soll.
Die Aussage

Die Klasse darf maximal 10 Methoden besitzen

verwendet die Methoden-Zahl-Metrik und fügt einen Schwellwert hinzu. Dadurch wird sie zum Güte- oder Qualitäts-Kriterium. Sie verwendet die Metrik, ist aber nicht identisch mit ihr. Das ist eine Fehlinterpretiation, die ich erstaunlich oft gehört habe.

Eine Metrik ist also zunächstmal ein Meßinstrument. Bevor man es anwenden kann, muß man sich überlegen was man mit den Ergebnissen anfängt wenn man sie hat. Und mehr noch: man muß sich erstmal darüber klar werden, ob man die Ergebnisse tatsächlich haben will. Klassen sollen in der Regel möglichst wenig Methoden haben, Methoden sollen möglichst kurz sein. Kurze Methoden heißt aber auch mehr Methoden. Sollte dann statt der Methoden-Zahl nicht lieber die durchschnittliche Methodenlänge gemessen werden?

Metriken sind — richtig verstanden — ein hilfreiches Werkzeug, aber:

A fool with a tool is still a fool

Diese Metrik ist tatsächlich zugleich ein selbsterfüllendes Qualitäts-Merkmal.

Merkmale für Code-Qualität

Nachdem wir die zu erfüllenden Anforderungen kennen, müssen wir nun Merkmale finden in denen sich die Anforderungen widerspiegeln. Merkmale, die es erlauben den Grad zu messen in dem die Anforderungen erfüllt sind. Es giebt eine unglaubliche Menge von Vorschlägen für Eigenschaften, Merkmalen oder Qualitäten die Code haben sollte oder nicht haben dürfen soll um als „guter Code“ zu gelten. Man kann diese Merkmale auch — zumindest teilweise — den genannten Anforderungen zuordnen.

Und an dieser Stelle fangen die Probleme an. Die Menge der Regeln ist riesig und die der diskutierten Auslegungen unüberschaubar. Tatsächlich ist die Vorstellung von Code-Qualität nicht absolut. Sie ist abhängig von Zeit, Kultur, verwendeter Technologie, Fachlichkeit und vielen anderen Faktoren. Die wenigen allgemeingültigen Regeln sind dermaßen abstrakt formuliert, daß sie kaum unmittelbar anwendbar sind. Und sobald man versucht ihre Anwendung zu konkretisieren, starten die Diskussionen.

Jedes Team und jede Organisation, die versucht die Code-Qualität zu verbessern muß damit beginnen ein gemeinsames Verständnis für die Qualität zu entwickeln. Ohne ein solches Verständnis findet man keine Einigung und Regeln werden entweder gar nicht erfüllt oder sie werden nur um der Erfüllung willen erfüllt. Gesetzte Regeln müssen verstanden und immer wieder auf ihre Sinnhaftigkeit hinterfragt werden. Das ist aufwändig und erfordert Engagement — wer ist bereit dafür Energei aufzubringen?

In den alten Tagen war es üblich, Code-Qualität am Verhältnis von Kommentar- zu Code-Zeilen zu messen. Je größer das Verhältnis desto besser. In der Folge sind viele Entwickler dazu übergegangen, den Code mit leeren Kommentar-Zeilen aufzufüllen. Die Metrik wird erfüllt, aber was hat das mit Qualität zu tun?

Metriken führen nicht zu Code von besserer Qualität,
sondern zu Code der die Metriken erfüllt.

Moderne Metriken scheinen besser geeignet zu sein. Man zählt die Methoden der Klasse, die Zeilen von Methoden und Funktionen, man mißt die Abdeckung des Codes mit Unit-Tests und die Kohärenz in Modulen. Aber was ändert das an der Einstellung des Entwicklers? Wer schnell viel Code generieren will (oder muß), der findet Wege die Metriken zu erfüllen ohne dabei die Code-Qualität ändern zu müssen.

Qualität ist die Einstellung des Entwicklers,
die vom Code reflektiert wird.

Macht das Regeln — und die Metriken die sie messen — überflüssig oder unsinnig? Nein. Der qualitätsorientierte Entwickler sollte alle Mittel nutzen — und zumindest ernsthaft erproben — um die Qualität zu verbessern. Die vielleicht beste Formulierung diese Gedankens stammt von Michael Feathers:

Clean Code always looks
like it was written by someone who cares.

Michael Feathers

Die Kommentar-Metrik zeigt aber noch ein anderes Problem. Keine Metrik kann messen wie hoch der Bezug ist den der Code zu seiner Semantik hat. Man könnte diese Eigenschaft als „Angemessenheit“ bezeichnen. Betrachten wir diese Zeile:

int x = a + b;

Sie ist zu umfangarm um irgendeine Aussage über ihre Qualität zu machen. Sobald wir aber die Variablen umbenennen und schreiben:

int differenz = soll + ist;

macht die Zeile überhaupt keinen Sinn mehr. Sie widerspricht sich plötzlich selbst. Die zusätzliche semantische Information die durch die Bezeichner transportiert wird ist für den Compiler schlichtweg unsichtbar. Ebenso wie die Information die gar nicht im Code enthalten ist, weil sie nur im Fachkonzept existiert.

Was können wir also über die meßbaren Merkmale von Code-Qualität sagen? Sobald wir festgelegt haben, welchen Regeln wir folgen möchten, können wir dazu Merkmale festlegen an denen wir die Code-Qualität messen können. Sobald sich unser Verständnis der Qualität ändert müssen wir die Merkmale anpassen. Ausreichend sind solche Merkmale aber nicht, die Übereinstimmung des Codes mit seiner Bedeutung können sie nicht erfassen.

Anforderungen an die Code-Qualität

Das Erste das wir brauchen sind Anforderungen. Ohne Anforderungen ist die Diskussion über Qualität sinnlos. Für funktionale Anforderungen ist das einfach: Wenn das Programm nicht richtig rechnet, ist es nutzlos — die Qualität ist dann unrettbar verloren. Man kann zwar darüber diskutiereen ob die eine oder andere funktionale Anforderung fallen gelassen werden kann, aber das ist ein Problem der Diplomatie, nicht der Technik.

Für die meisten nicht-funktionalen Anforderungen gilt das auch. Wenn es um technische Anforderungen geht — wie zum Beispiel die Reaktionszeit — lassen sich in der Regel Anforderungen formulieren, die die Merkmale für ihre Erfüllung gleich mitbringen. Am Beispiel der Reaktionszeit war das zu erkennen. Schwieriger sind Forderungen nach der Bedienbarkeit, da muß man bisweilen die humanistischen Wissenschaften bemühen um etwa festzulegen was „leichte“ oder „intuitive“ Bedienbarkeit bedeutet.

Was aber müssen wir (an-)fordern, wenn es um Code-Qualität geht? Beginnen wir am menschlichen Ende der Pipeline: Wer hat denn überhaupt ein Interesse an Code-Qualität? Für die Endanwender von Software ist entscheiden, daß die Software macht was sie soll,. Sie soll ihre Funktion erfüllen, und das schnell und unkompliziert — wie sie das tut ist dem Anwender egal; die meisten Anwender würden es auch gar nicht verstehen (keine Kritik: das ist ja auch nicht ihr Job). Die Auftraggeber — also üblicherweise diejenigen die die Herstellung der Software bezahlen — haben ein Interesse an zufriedenen Anwendern und an niedrigen Kosten. Wie die Anwender sind sie fachlich motiviert und interssieren sich ebenfalls nicht für die Technik. Und selbst die Techniker vom Betrieb haben kein ursächliches Interesse am Code. Sie benötigen eine saubere Dokumentation, aussagekräftige Log-Ausgaben und angemessene Konfigurations-Möglichkeiten.

Wer interessiert sich nun aber für den Code? Es sind die Entwickler. Leider sind es nicht immer diejenigen die den Code schreiben; aber immer diejenigen die die Anwendung warten. Sie müssen Fehler finden und fixen, sie müssen Anpassungen und Erweiterungen durchführen, sie müssen Portierungen und Updates duchführen. Sie sind die Nutznießer guter Code-Qualität, sie haben ein Interess daran — zumindest sollten sie es haben.

Damit haben wir schu schon die wichtigsten Anforderungen, die die Code-Qualität bestimmen. Sie können unterschiedlich gewichtet sein, es können andere Anforderungen hinzukommen, aber immer werden diese drei Anforderungen die entscheidende Rolle spielen:

  • Wartbarkeit
  • Änderbarkeit
  • Erweiterbarkeit

Sie sind von Natur aus nicht-funktional, denn ob der Code wartbar oder änderbar ist oder nicht, ist völlig unabhängig davon ob er seine Funktion erfüllt oder nicht. Um kein Mißverständnis aufkommen zu lassen: Auch wenn die Code-Qualität für die Erfüllung dieser Anforderungen von entscheidender Bedeutung ist, giebt es weitere Faktoren die sie beeinflussen — allen voran die Architektur. Aber hier geht es erstmal nur um die Code-Qualität.

Code-Qualität, Vorbemerkung

Bevor man über einen Begriff diskutiert, muß man festlegen, was man damit eigentlich meint. Wir können erstmal beim landläufigen Verständnis dafür bleiben, was „Code“ ist, aber was ist eigentlich „Qualität“?

Der Bedeutung des Wortes nach bezeichent „Qualität“ zunächst „die Beschaffenkeit von irgendwas“. Meint also irgendeine Eigenart des betrachteten Objekts, wie die Farbe oder die Größe. Dem Wesen nach bedeutet (eine) Qualität also (eine) Eigenart die irgendwie ausgeprägt sein kann. Eine allgemeine oder absolute Bedeutung hat der Begriff zunächst nicht — es macht also keinen Sinn von der Qualität einer Sache zu sprechen. Auch ist noch keine Aussage darüber gemacht in welcher Weise oder Menge das Objekt die Eigenschaft erfüllt. Und auch nicht, ob dieser Zustandgut ist oder schlecht. Oder so gefragt: Hat das Objekt mehr oder weniger? Ist mehr besser oder schlechter?

Um mit dem Begriff „Qualität“ etwas sinnvolles bezeichnen zu könnne, definiert ihn die ISO so:

Grad, in dem ein Satz inhärenter Merkmale eines Objekts Anforderungen erfüllt.

Es geht darum, daß das Objekt Anforderungen erfüllen muß; gemessen an einer definierten Menge von Eigenschaften die dem Objekt zu eigen sind (also nicht zugesprochen werden). Anhand der Merkmale soll bestimmt werden, inwieweit die Anforderungen erfüllt sind; die Merkmale müssen also meßbar sein, einen Bezug zu den Anforderungen haben und Aufschluß darüber geben, ob die Anforderungen erfüllt sind.

Zu abstrakt? Ein Computer-Programm wird nicht verwendet, wenn die Berechnung zu lange dauert. Man verlangt also als Anforderung: 5 ms nach Eingabe muß das Ergebnis am Bildschirm erscheinen. Das Merkmal ist die Verarbeitungsgeschwindigkeit (daß diese vom verwendeten Computer abhängt übersehen wir hier mal). Der Grad der Erfüllung ist die Differenz zwischen den 5 ms und der tatsächlichen Ausführungszeit.

Um die Qualität bestimmen zu können benötigen wir also:

  • Anforderungen
  • Merkmale die die Erfüllung dieser Anforderungen widerspiegeln
  • Einen Weg diese Merkmale am Objekt zu messen
  • Schwellwerte, die die Erfüllung der Anforderung signalisieren

Um von der Qualität eines Objekts sprechen zu können, benötigen wir also immer einen Kontext. Es muß klar sein, welche Anforderungen vom Objekt erfüllt werden sollen. Die Anforderungen und die Mekmale, die als Indikator für deren Erfüllung dienen, müssen feststehen; dann können wir darauf verzichten sie jedesmal aufzuzählen und sprechen von der Qualität des Objekts.

Warum Code-Qualität wichtig ist

An jedem Software-Projekt ist eine Unmenge von Leuten beteiligt die die unterschiedlichsten Rollen wahrnehmen. Da gibt es Projektleiter, Fachspezialisten, Tester, Architekten, Designer und was sonst noch alles. Je größer das Projekt, desto größer die Zahl der Beteiligten. Und wenn die Software in den Betrieb geht kommen noch mehr Leute und noch mehr Rollen hinzu. Software ist — heute mehr denn je — ein Team-Produkt.

Wer in obiger Aufzählung nicht erwähnt wurde, das sind die Coder, die Programmierer oder Software-Ingenieure. Diejenigen, die — in der Sprache der Machine — das formulieren, was die Maschine später zu tun hat. Ihnen kommt eine einzigartige Bedeutung zu. Denn nüchtern betrachtet ist ihre Arbeit das einzige, was am Ende übrig bleibt und tatsächlich „etwas tut“ wenn die Software live geht.

Das bedeutet nicht, daß der Rest des Teams überflüssig wäre — ganz im Gegenteil. Erst die gemeinsame Anstrengung macht den Erfolg des Projektes überhaupt erst möglich. Der Projekt-Plan ist wichtig um das Projekt durchzuführen, verschwindet aber wenn das Projekt abgeschlossen ist. Die Arbeit der Tester ist ein wichtiger Bestandteil des Entwicklungsprozesses, aber am Ende läuft nur noch der Code; von den Testläufen ist am Ende nur noch das Ergebnis übrig.

Es ist so ähnlich wie bei einer militärischen Operation. Von vier eingesetzten Soldaten werden drei für Transport, Versorgung und Unterstützung der Truppen — von der Verpflegung bis zur Flugabwehr — benötigt. Der eigentlichen Kampf — Mann gegen Mann — wird in der ganzen Kette von einer erstaunlich kleinen Gruppe geführt. Alle Beteiligten sind wichtig, alle Beteiligten setzen sich sich Lebensgefahr aus, aber die Schlacht wird letztenendes von den Kampftruppen entschieden.

Wenn dann die Anwendung im Betrieb ist, das Team sich anderen Projekten widmet und in der Software ein Problem auftritt, dann zeigt sich wie gut der Coder tatsächlich gearbeitet hat. Denn oft genug sind diejenigen die die Anwendunng betreuen nicht die gleichen wie die die sie gebaut haben. Dann zeigt sich, ob der Code sauber entwickelt oder einfach nur heruntergerotzt wurde.

Jeder im Projekt muß solide Arbeit leisten wenn das Endprodukt erfolgreich sein soll. Aber wenn das was der Coder baut nur gerade eben das tut was die Anforderungen verlangen, schläft in der Anwendung eine Bombe die mit Sicherheit dann hochgeht, wenn man es am wenigsten gebrauchen kann. Wenn dann Fragen auftauchen wie „Was macht eigentlich diese Funktion?“ oder „Was geschieht, wenn man diesen Wert ändert?“, dann zahlt man doppelt und dreifach was man im Projekt an der Entwicklung gespart hat.