Wie kommen die Bugs ins Programm?

Na endlich! Auf diesen Artikel haben Sie bestimmt lange gewartet! Wir erklären, wie die Fehler ins Programm kommen, warum bereits funktionierende Teile wieder kaputt gehen können und warum es manchmal so schwer ist, die Probleme unter Kontrolle zu bringen. 

Manchmal kann es sehr frustrierend sein, wenn mal wieder die Bug-Liste länger und länger wird. Man fragt sich als Nicht-Programmierer vielleicht, wie es eigentlich dazu kommen kann, dass es derart viele Fehler in der Software gibt. Andere Firmen scheinen das ja auch irgendwie zu meistern. Und warum gehen eigentlich Sachen kaputt, die vorher korrekt funktioniert haben? Was machen die Codierer eigentlich den ganzen Tag für Mist?
Die Wahrheit ist, dass es sehr viele Gründe für Bugs im Code gibt. Im Folgenden soll auf die einzelnen Ursachen eingegangen und Lösungswege aufgezeigt werden.
Wir haben an der Stelle aber ein kleines Problem: Die Arbeit an Code ist extrem abstrakt, beinhaltet sehr viele komplizierte Mechanismen, die man als Außenstehender nur schwer begreifen kann (wenn man sich nicht wenigstens ein oder zwei Jahre mit dem Thema auseinander gesetzt hat) und man stößt auf Probleme, die es bei anderen Arbeiten so nicht gibt. Wir wollen es trotzdem mal versuchen.

Bugs sind normal, wirklich.

Grundsätzlich gilt, dass Fehler in einer Software nichts ungewöhnliches sind. Es ist logisch, dass je großer, je komplexer, je vielseitiger ein Programm ist, desto mehr Bugs enthalten sein müssen. Mit wachsender Zahl an Möglichkeiten und Optionen gibt es mehr, was man unter Kontrolle bringen muss. So wie es beim Fahrzeugbau zu Montagefehlern kommen kann, kann es passieren, dass ein Programmierer etwas falsch codiert – wir haben zwar göttliche Kräfte, sind aber auch nur Menschen. Während aber die falsch montierten Autos nur an ein paar Kunden ausgeliefert werden, erhalten beim Programm alle Kunden den fehlerhaften Code. Dafür kann man die Fehler leichter korrigieren ;-).
Trotzdem scheint es bei anderen Softwarefirmen weniger Probleme zu geben. Aber das ist ein Trugbild. Als Außenseiter hat man keinen Einblick auf die tatsächliche Liste an Problemen bei anderen. Man hat nur das subjektive Empfinden und kennt selber auch nicht alle Bugs in Fremdprogrammen. Auch Google und Facebook bleiben von Fehlern nicht verschont. Sie setzen aber Strukturen ein, die die Gesamtzahl an Fehlern deutlich verringert (dazu später mehr).

Manchmal sind Bugs keine Bugs

Programmierer sind öfters mal – sagen wir – überrascht, was manchmal als Bug durchgeht. Nicht selten liegt aus rein objektiver Sicht kein Fehler vor. Das kann beispielsweise sein, wenn die ursprüngliche Funktionsdefinition unzureichend war. Wenn man dem Codierer sagt, die Software soll Word-Dateien lesen und man merkt, dass Kunden lieber Excel-Dateien verwenden und sich wundern, warum das nicht geht, dann ist es nicht Schuld des Programmierers, dass das Programm keine Excel-Dateien verarbeiten kann, auch wenn es für den Kunden wie ein Fehler aussieht.
Es gibt noch viele weitere Beispiele. Wenn man etwa das subjektive Gefühl hat, dass das Programm zu langsam ist, dann liegt auch kein Fehler vor.
Ein Bug ist wirklich nur dann ein Bug, wenn das Programm etwas anderes macht, als das, was man den Codierern zuvor exakt vorgegeben hat (und auch nur dann, wenn sich die Definition nicht alle drei Stunden ändert, weil fünf Leute vorgaben machen oder der Kunde nicht weiß, was er eigentlich möchte/braucht). Wenn der Programmierer widersprüchliche oder falsche Anweisungen bekommt, woher sollte er denn wissen, was er wirklich machen muss? Wie soll er so eine einheitliche, stabile Programmstruktur aufbauen? Kann er sich so überhaupt Zeit nehmen, es richtig zu machen? Das ist übrigens auch der Grund, weshalb es sinnvoll ist, dass ein Programmierer die Anweisungen immer nur von einem einzigen P. O. (Product-Owner) erhält und von sonst niemandem. Gemeint ist nicht “immer nur einer gleichzeitig” sondern “es gibt überhaupt nur eine Person, die beauftragen darf”.

Keine Tests sind keine gute Idee

Auch heute noch sparen viele Firmen an den Tests, aber dann muss man auch mit den Konsequenzen leben. Das Schlimme ist, dass manchmal auch Programmierer blind gegenüber den Vorteilen von Tests sind, nach dem Motto

“Wir bekommen das auch irgendwie so schon hin, dass die Software läuft.”

(siehe oben “Codierer sind auch nur Menschen”). Man sieht: Nö, läuft nicht. Gerade deshalb muss man etwas Zeit und Geld in Tests investieren, auch wenn man die Vorteile nicht direkt zu spüren bekommt. Das Kosten-Nutzen-Verhältnis spricht jedenfalls für sich. Ich weiß, es ist immer schwer, etwas zu erklären bzw. zu vermitteln, was nur sehr indirekt wirkt und erst nach einer gewissen Zeit Ergebnisse zeigt. Allerdings können Tests unbestechlich beweisen, dass etwas Bestimmtes funktioniert oder eben nicht. Je mehr man testet, desto weniger Fehler entgehen einem. In einer perfekten Welt würde man sogar die Tests vor dem eigentlichen Code erstellen. Sobald der Code den Test besteht, gilt er als fertig. Eine bessere Vorgabe für das, was er machen soll, kann sich ein Programmierer eigentlich nicht wünschen – und keine Seite kann sich herausreden! Außerdem können Tests ja immer wieder ausgeführt werden, auch nach ein oder zwei Jahren. Und gute Tests laufen automatisch, sodass man schlicht einen kleinen Rechner aufstellen muss, der ganz alleine herumrödelt und Sie auf Fehler hinweist, bevor es die Kunden tun. Dazu kommt, dass manuelle Tests aufwendig sind, nervig noch dazu und irgendwann hat niemand mehr Zeit und Lust, die Software per Hand intensiv zu prüfen.

Alter Code sind Altlasten

Warum sollte alter Code Schwierigkeiten machen? Er ist doch bewährt, weil viel-benutzt! Das ist aber falsch gedacht. Software ist wie ein lebender Organismus. Sie wächst, Dinge verwachsen miteinander, Teile verändern sich, Verbindungen lösen sich, Sachen werden entfernt. Das bedeutet, dass sich Funktionen absichtlich oder unabsichtlich ständig dynamisch verändern, vor allem wenn ein ganzes Team am Produkt arbeitet. Je größer die Abhängigkeiten von Features in einem Programm sind, desto stärker und unberechenbarer sind die Ergebnisse, sobald es eine Änderung an einer Stelle gibt. Und alter Code tendiert durch Vielbenutzung einfach dazu, sich an alle möglichen andere Stellen zu koppeln (= Abhängigkeit).
Es ist wie beim Hausbau: Am Anfang war ein Gebäude. Als es zu klein war, hat man an alle möglichen Seiten weitere Gebäude angebaut. Und sobald das Mittelteil abgerissen werden muss, bekommen wir Probleme im ganzen Komplex.
Leider altert Code mit der Zeit. Zum einen erkennt man langsam aber sicher, dass man einen Teil besser hätte realisieren können (leichter wartbar, leichter erweiterbar, bessere Testbarkeit, bessere Performanz), zum anderen hat man immer wieder kleine Eingriffe (zur Korrektur oder um die Funktionalität zu erweitern) und diese werden mit zunehmender Anzahl zur Pfusch-Bastelarbeit. Nach der zehnten Schönheitsoperation sieht halt jeder aus wie ein Zombie. Darum führt kein Weg daran vorbei, große Bereiche des Codes nach ein paar Jahren ganz und gar einzureißen und komplett neu zu bauen. Um dabei die Garantie zu haben, dass der neue Code mindestens genauso gut ist wie der alte, braucht man Mechanismen zur Qualitätssicherung (siehe oben: Die damaligen Tests kann man wiederverwenden, wenn sich eine Funktion nicht ändern soll).

Falsche Arbeitsweise führt zu falscher Funktionalität

Dieses Thema habe ich in den obigen Absätzen bereits angeschnitten. Auch die Art und Weise wie das Team arbeitet hat selbstverständlich Auswirkungen auf die Qualität des Produkts. Das ist jedoch in vielen anderen Berufen genauso. Viele Faktoren können letztlich dazu führen, dass man die Professionalität vergisst und sich wild durchkämpft. Damit lindert man nur die Symptome, die Krankheit lässt sich aber nur durch eine kluge und sachliche Vorgehensweise beenden.
Stress und Zeitmangel: Wenn die Kunden ganz dringend ein Feature brauchen, das vielleicht sogar schon bezahlt ist, und ohne welches sie ganz und gar nicht produktiv arbeiten können, dann wird Druck auf die Codierer ausgeübt. In vielen Firmen ist das sogar leider die Regel. Allerdings, wenn man Code (also etwas Handwerkliches, das man nicht einfach so zusammenkopieren kann) wie am Fließband produzieren muss, dann sollte man sich auch nicht über eine schlechte Qualität wundern. Natürlich lassen sich solche Situationen nicht vermeiden. Dafür wurde der Begriff “technische Schulden” erfunden. Man macht also zunächst etwas, was eine Verpflichtung schafft, dass man es in besseren Zeiten wieder in Ordnung bringt. Dafür muss es aber auch bessere Zeiten geben, sonst ist man irgendwann technisch insolvent.
Wissensblase: Sehr viele Berufe haben es so an sich, dass sich das Wissen schnell weiterentwickelt und es immer wieder neue Methoden, Werkzeuge, Erfahrungen und Prinzipien gibt. Selbstverständlich muss man nicht jede Sau reiten, die durchs Dorf getrieben wird. Aber gerade in der Programmierung erweisen sich manche Neuigkeiten nach ein paar Jahren als der richtige Weg. Diesen Weg sollte man konsequenterweise bereit sein, zu beschreiten. Denn wenn man nicht bereit ist, sich weiter zu entwickeln und damit sich und die Software zu verbessern, kann man schon bald nicht mehr mit der Konkurrenz mithalten, die plötzlich flexibler und schneller Features implementiert, günstiger produziert und eine performantere und stabilere Software präsentiert – und der Ahnungslose rätselt, warum das so ist.
Teamfähigkeit: Wenn jeder sein eigenes Süppchen kocht und am Schluss alles zusammengekippt wird, wird es schlecht schmecken. Das gilt für Programmierer unter sich, denn wenn man sich nicht auf bestimmte Frameworks (also fertige Features, die man kaufen/herunterladen und leicht einbinden kann) und Code-Konventionen (Schreib- und Strukturierungsstil) einigt, dann wird die Software zu einem undurchsichtigen Knäuel von Gekröse. Das gleiche gilt für Zuständigkeiten und die Aufteilung der Bereiche und Aufgaben. Es gilt jedoch auch für die Zusammenarbeit zwischen Codierern und dem Rest der Firma (siehe oben: ein einziger P. O. pro Software/Produkt/Produkt-Abschnitt).
Werkzeuge: Im Vergleich zu anderen Industriezweigen ermöglicht die Software-Branche eine vergleichsweise günstige Einrichtung eines Arbeitsplatzes. Mit einem guten Rechner und drei Monitoren hat man bereits den Großteil. Allerdings sollte man den Codierern auch darüber hinaus Möglichkeiten bieten. So sollten Geld und Zeit eingeplant werden für: Test-Server, Software-Tools (für Tests, zum Messen von Code-Werten usw.), ergonomische Maus und Tastatur (Gesundheit!), Weiterbildungen und  Fachliteratur.
Wichtig ist es auch, eine Balance zwischen Sicherheit und Legalität zum einen und Freiheit zum anderen zu finden.
Niemand sollte beispielsweise an der Firewall vorbei etwas in das Firmennetzwerk schleusen können. Auf der anderen Seite müssen Programmierer jedoch spontan und schnell Software-Tools herunterladen und installieren können, um sich just-in-time die Hilfswerkzeuge anzuschaffen, die sie zum Lösen ihrer Probleme brauchen. Das können Code-Analyse-Werkzeuge sein, aber auch Editoren mit Formatierungs- und Markierungsfunktion. Die Lösung hierfür ist, einen System-Administrator als ständigen Ansprechpartner direkt in der Firma vor Ort zu haben. Dessen Reaktionszeit darf die Feierabendgrenze auf keinen Fall überschreiten, sonst droht Produktionsstillstand! 

Fallbeispiel: Steuerarten

Schauen wir und doch mal ein Szenario an. Nehmen wir an, wir bieten derzeit  eine Software auf dem Markt an, mit der man Dienstleistungen projektieren und Rechnungen schreiben kann. Zuerst sollte es eine einfache und günstige Alternative zu den Produkten der Big Player werden. Nachdem jedoch immer mehr Kunden dazugekommen sind – teils auch Großkunden – stehen wir unter dem Druck, immer wieder Anpassungen vorzunehmen, damit diese Kunden die Software z. B. auch in ausländischen Zweigstellen verwenden können.

Immer wieder wollten Kunden nicht nur die deutsche Steuerart für Dienstleistungen zur Rechnung hinzufügen, sondern alternativ auch die polnische, portugiesische, spanische, italienische…
Unser Neukunde möchte das Programm in Frankreich verwenden.

Ein Hinweis noch: Sie müssen die Code-Beispiele nicht verstehen. Es reicht hier völlig, wenn Sie den Code (der keine richtige Programmiersprache darstellt; sog. Pseudocode) einfach auf sich wirken lassen (bezüglich Übersichtlichkeit, Umfang, Struktur etc.).

Kunden-Betreuer: “Hey, unser neuer Kunde braucht die französische Steuerart zur Auswahl. Der ist schon ein bisschen genervt, dass wir uns erst jetzt, zwei Monate nach dem Kauf, um ihn kümmern. Ich habe ihm gesagt, dass das bis Ende der Woche eingebaut ist. Könntest du das bitte machen? Es wäre sehr wichtig.
Programmierer: “Naja, das ist nicht ideal, weil wir noch andere dringende Sachen auf der To-Do-Liste haben. Ich kann aber mal schauen, ob ich das irgendwo dazwischenquetsche.
Kunden-Betreuer: “Danke! Wie gesagt, das ist schon wichtig.

Der Programmierer schaut in den Code:

function calculateRechnung(preis, land) returns number{
    if (land.is("Deutschland")){
        preis = preis * 1.05;
    } else if (land.is("Polen")) {
        preis = preis * 1.08;
    } else if (land.is("Portugal")) {
        preis = preis * 1.05;
    } else if (land.is("Spanien")) {
        preis = preis * 1.11;
    } else if (land.is("Italien")) { 
        preis = preis * 1.02;
    }
    return preis;
}

Programmierer: “Hm, ja, das ist jetzt nicht gerade ultra vorbildlich. Aber das sah früher einmal besser aus.

function calculateRechnung(preis) returns number{ 
    return preis * 1.05;
}

Programmierer: “Das war vor den anderen Ländern. Ok, aber so wie es jetzt ist, könnte es mal zum Problem werden. Allerdings habe ich gerade echt keine Zeit dafür und es muss ja auch schnell gehen. Dann klatschen wir Frankreich einfach nur mit dazu…

function calculateRechnung(preis, land) returns number{ 
    if (land.is("Deutschland")){ 
        preis = preis * 1.05; 
    } else if (land.is("Polen")) { 
        preis = preis * 1.08; 
    } else if (land.is("Portugal")) { 
        preis = preis * 1.05; 
    } else if (land.is("Spanien")) { 
        preis = preis * 1.11; 
    } else if (land.is("Italien")) { 
        preis = preis * 1.02;
    } else if (land.is("Frankreich")) { 
        preis = preis * 1.15; } 
    return preis; 
}

Nach einem Monat hat sich der Kunde entschlossen, die Software auch im französisch-sprachigen Teil Kanadas einzusetzen.

Product-Owner: “Unser Kunde möchte das Programm jetzt auch in Kanada einsetzen. Das heißt, wir brauchen noch die Steuerart “Kanada” mit 14% Aufschlag. Ich würde das gerne für die nächste Woche einplanen.
Programmierer: “In Ordnung, können wir machen.

Der Programmierer schaut ein paar Tage später wieder in den Code:

function CalculateRechnung(preis, land) returns number{ 
    if (land.is("Deutschland")){ 
        preis = preis * 1.05; 
    } else if (land.is("Polen")) { 
        preis = preis * 1.08; 
    } else if (land.is("Portugal")) { 
        preis = preis * 1.05; 
    } else if (land.is("Spanien")) { 
        preis = preis * 1.11; 
    } else if (land.is("Italien")) { 
        preis = preis * 1.02;
    } else if (land.is("Frankreich")) { 
        preis = preis * 1.15; 
    } else if (land.is("Belgien")) { 
        preis = preis * 1.10; 
    } else if (land.is("Dänemark")) { 
        preis = preis * 1.07; 
    } else if (land.is("Holland")) { 
        preis = preis * 1.09; 
    } else if (land.is("Luxemburg")) { 
        preis = preis * 1.10; 
    } 
    return preis; 
}

Programmierer: “Na hoppla! Wie kann denn das sein? Da hat wohl jemand einfach das komplette Benelux-Gebiet reingepackt und sich nicht einmal angestrengt, den Code besser zu machen. Das kann doch nicht endlos so weiter gehen! Wer soll denn das nach der halben Weltkugel noch lesen können? Und der Code für die Multiplikation ist auch pro Land vorhanden. Das könnte man doch zusammenziehen! Refactoring!

enumeration Tax{
    GERMANY,
    PORTUGAL,
    SPAIN,
    ITALY,
    FRANCE,
    BELGIUM,
    DENMARK,
    NETHERLANDS,
    LUXEMBOURG,
    KANADA;

    function getTaxFactor() returns number{
        switch (this)
        {
            case GERMANY: return 1.05;
            case PORTUGAL: return 1.08;
            case SPAIN: return 1.05;
            case ITALY: return 1.11;
            case FRANCE: return 1.02;
            case BELGIUM: return 1.15;
            case DENMARK: return 1.10;
            case NETHERLANDS: return 1.07;
            case LUXEMBOURG: return 1.09;
            case KANADA: return 1.14;
        }
    }
}
function calculateBill(price, countryTax) returns number{
    return price * countryTax.getTaxFactor();
}

Was ist hier nun passiert? Der Entwickler hat den Code auf zwei Code-Teile gesplittet und damit nach Aufgaben aufgeteilt: Auf der einen Seite haben wir das Abbilden von Ländern auf den einzurechnenden Faktor, auf der anderen Seite haben wir die Formel zur Berechnung an sich. Dadurch findet man sich besser zurecht, weil man nicht nach bestimmten Stellen suchen muss. Eine Aufgabe = eine Stelle = gut (heißt in der Fachsprache SRP, Single Responsibility Principle).
Außerdem hat der Programmierer den Code nun komplett und konsequent ins Englische übersetzt. In Anbetracht der Tatsache, dass man vielleicht irgendwann auch Mitarbeiter hat, die kein Deutsch sprechen, ist das eine gute Entscheidung. Denn ein solcher Kollege würde nicht “Mitarbeiter”, sondern “Meiterbeiter” schreiben. Der Code wäre dann nicht deutsch, nicht englisch, sondern Quatsch. Und nach Quatsch-Begriffen kann man nicht gezielt suchen und man versteht sie auch nicht.
Aber: Ich weiß nicht, ob es Ihnen aufgefallen ist. Entgegen seiner Nationalhymne ist Polen nun verloren. Dadurch haben sich auch die Faktoren aus Versehen verschoben. Gäbe es für diese Funktionalität einen Code-Test (auch Unit-Test genannt), dann wäre das dem Entwickler aufgefallen. So aber ist eine seit langem funktionierende Stelle plötzlich kaputt gegangen. 
Es kommt aber noch härter:

Kunden-Betreuer: “Der Kunde meint, das funktioniert noch nicht.
Programmierer: “Ich habe das aber einmal ausgeführt und da ging es. Komisch. Was genau geht denn nicht?
Kunden-Betreuer: “Es wird der falsche Faktor genommen. Für Dienstleistungen beträgt die Steuer 7 %.
Programmierer: “Mein P.O. meinte aber 14 %.
Kunden-Betreuer: “Nein, der Kunde meint 7 %.

enumeration Tax{ 
    GERMANY, 
    PORTUGAL, 
    SPAIN, 
    ITALY, 
    FRANCE, 
    BELGIUM, 
    DENMARK, 
    NETHERLANDS, 
    LUXEMBOURG,
    KANADA; 

    function getTaxFactor() returns number{ 
        switch (this) { 
            case GERMANY: return 1.05; 
            case PORTUGAL: return 1.08; 
            case SPAIN: return 1.05; 
            case ITALY: return 1.11; 
            case FRANCE: return 1.02; 
            case BELGIUM: return 1.15; 
            case DENMARK: return 1.10; 
            case NETHERLANDS: return 1.07; 
            case LUXEMBOURG: return 1.09;
            case KANADA: return 1.07; 
        }
    } 
}

Product-Owner: “Ich wollte das gerade dem Kunden zeigen, aber es funktioniert plötzlich nicht mehr. Es sind jetzt so um die 7 %.
Programmierer: “Ja, der Kunden-Betreuer meinte, es müssen 7 % sein. Das hat der Kunde gesagt.
Product-Owner: “Komisch. In der E-Mail steht, dass es 14 % sind.
Programmierer: “Ihr müsst euch schon entscheiden.

Es wird also eine Online-Konferenz mit dem Kunden einberufen.

Product-Owner: “Hallo. Wir haben hier widersprüchliche Angaben über den genauen Betrag der Steuer für Dienstleistungen in Kanada. Sind es 7 % oder 14 %?
Kunde: “Es gibt fünf Steuerarten, je nach Ware oder Dienstleistung: 0, 5, 7, 11 und 14 %.
Kunden-Betreuer: “Also hatte ich Recht.
Product-Owner: “Und ich auch.
Kunde: “Hätten Sie das nicht einfach googlen können? Warum muss ICH Ihnen das erklären?
Programmierer: “

Der Programmierer muss sich jetzt etwas ausdenken.

  • Er könnte entweder eine zweite Kategorie, neben dem Land, einführen – das wäre Code-mäßig eher kompliziert, würde länger dauern, aber dafür hätte man eine saubere Trennung der Kategorisierung. Das ist insbesondere nützlich, wenn in Zukunft noch mehr Kategorien dazukommen (z.B. “Preisfaktor für Großleistungen”, “Famous-Client-Factor” etc.).
  • Er könnte einfach die Liste mit Kanada-Varianten erweitern. Damit vermischt man Länder und Dienstleistungsarten, bringt somit mehr Chaos in den Code, aber es geht schneller und leichter.

Drei Mal dürfen Sie raten…

enumeration Tax{ 
    GERMANY, 
    PORTUGAL, 
    SPAIN, 
    ITALY, 
    FRANCE, 
    BELGIUM, 
    DENMARK, 
    NETHERLANDS, 
    LUXEMBOURG, 
    KANADA_HEALTH,
    KANADA_FOOD,
    KANADA_REPAIR,
    KANADA_SERVICE,
    KANADA_PRODUCTIVE;

    function getTaxFactor() returns number{ 
        switch (this) { 
            case GERMANY: return 1.05; 
            case PORTUGAL: return 1.08; 
            case SPAIN: return 1.05; 
            case ITALY: return 1.11; 
            case FRANCE: return 1.02; 
            case BELGIUM: return 1.15; 
            case DENMARK: return 1.10; 
            case NETHERLANDS: return 1.07; 
            case LUXEMBOURG: return 1.09; 
            case KANADA_HEALTH: return 1.00; 
            case KANADA_FOOD: return 1.05; 
            case KANADA_REPAIR: return 1.07; 
            case KANADA_SERVICE: return 1.11; 
            case KANADA_PRODUCTIVE: return 1.14; 
        } 
    } 
}

Man braucht nicht zu erwähnen, dass der Programmierer den inzwischen unpassenden Variablen-Namen “countryTax” in “CalculateBill” so lässt. “taxVariation” oder “taxType” wäre nun besser, da es ja nicht mehr nur um das Land, sondern auch um die Dienstleistungsart geht. Würde der Programmierer den Code mit einem anderen Programmierer reviewen, also den Umbau/die Lösung im Detail noch einmal mit einem anderen Codierer sorgfältig  besprechen, wäre diese Kleinigkeit vielleicht noch aufgefallen. Unser Programmierer verzichtet darauf, weil “das Feature ja grundsätzlich funktioniert und die letzte Änderung nicht so groß war”.

Das Beispiel zeigt sehr gut, dass alle Probleme zusammen dafür sorgen, dass sich Bugs hineinschleichen und dass Code an Qualität verliert. Deshalb sollte jeder Mitarbeiter sein Bestes geben und seine Arbeitsmoral nicht verlieren. Gleichzeitig muss man Prozesse in der Firma stets hinterfragen und optimieren. Was man letztlich durch eine schnelle Lösung an Zeit spart, kommt hinterher durch Mehraufwand zweifach wieder zurück. Das sieht man auch an diesem Beispiel: Der Programmierer musste mehrmals Hand anlegen, P.O. und Kunden-Betreuer mussten die Funktionalität mehrmals verifizieren, der Kunde wurde belästigt, es werden mehrere (!) Programmierer den Polen-Bug und den Bug/die Bugs mit den verschobenen Faktoren lösen müssen und der nächste Codierer, der die Funktionalität erweitert, muss den Code zunächst auf weitere Kategorien umbauen bevor er richtig beginnen kann (und wenn er etwas kaputt macht, gibt es wieder keinen Test der darauf hinweist). Eine “Lose-Lose-Situation”.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

WordPress Cookie Plugin von Real Cookie Banner