Mit Intelligenten Fehlermanagement kann man sich in den Fuß schießen

Ich kann ja nun persönlich auf 30 Jahre Softwareentwicklung zurückblicken, und was ich definitiv sagen kann ist, dass das Fehlermanagement deutlich komplizierter geworden ist. Ohne auf Details einzugehen ist es tatsächlich so, dass Softwaresysteme früher sehr viel deterministischer waren. Es gab erheblich weniger Möglichkeiten (auch in der Erfassung und der Bildschirmmaskensteuerung) und somit auch weniger denkbare Fehlerkonstellationen. Wenn eine Software so gebaut ist, dass nur eine Sache nach der anderen gemacht wird (d.h. auch eine Eingabe nach der anderen in einer definierten Eingabereihenfolge verarbeitet wird), dann hat man tatsächlich eine realistische Chance sämtliche denkbaren Fehlersituationen Stück für Stück zu berücksichtigen. Heutzutage hat man dagegen Systeme, die eine nahezu beliebige Erfassungs- und Eingabereihenfolge gestatten. Wenn nun einzelne Eingaben Abhängigkeiten untereinander aufweisen, so wird es richtig kompliziert, denn einerseits soll die Freiheit der Eingabe gewahrt bleiben, andererseits sollen Fehleingaben ausgeschlossen werden. Um der Sache noch eine Komplexitätsstufe hinzuzufügen, sollen häufig bereits während der Eingabe Jobs ablaufen, die die weitere Erfassung vereinfachen. Selbstverständlich dürfen unsinnige Eingaben oder Daten nicht zu einem Absturz führen, sondern die Programme müssen „intelligent“ darauf reagieren. Tatsächlich ist es absolut unmöglich, bei jedem Eingabefeld sämtliche Kombinationen mit anderen Feldern zu berücksichtigen (alleine bei vier Feldern gibt es schon 32 Möglichkeiten), also werden nur als problematisch erkannte Szenarien berücksichtigt. Das führt jedoch sehr schnell zu Problemen, denn jeder erfahrene Programmierer weiß, dass es egal ist, wie viele Szenarien berücksichtigt werden, beim Kunden wird sofort eines auftreten, dass nicht berücksichtigt wurde. Der vorausschauende Entwickler baut also zusätzliche Schutzmechanismen ein, die dann greifen, wenn eine problematische Eingabe nicht erkannt wurde. Dann gibt’s noch Schutzmechanismen für die Schutzmechanismen. Das ganze führt dann zwar zu einem sehr stabilem Code, hat jedoch auch den überaus negativen Effekt, dass Fehler als solche gegebenenfalls nicht erkannt werden, dann zu Folgefehlern führen, die vielleicht auch nicht erkannt werden, weil die Software auch darauf noch „intelligent“ reagiert und dann irgendwann  ein Fehler auftritt, der nicht mehr abgefangen wird, sozusagen als Folge der Folge der Folge. Und genau diesen letzten Fehler kann man dann nicht mehr analysieren, weil nicht mehr festzustellen ist, was eigentlich der ursprüngliche Auslöser war. Es ist dann schon fast Zufall, wenn der ursprüngliche Fehler dann doch irgendwann gefunden wird. In der Regel ist das dann eine Anwendereingabe, die irgendwie nicht sinnvoll war, mit der das Programm jedoch intelligent umgegangen ist (ohne wirklich intelligent zu sein).
Wenn man sich mal die verschiedenen Protokolle (egal von welchem Betriebssystem) ansieht, dann ist man bass erstaunt, wie häufig soetwas vorkommt.
Derartige Probleme lassen sich tatsächlich per se nicht lösen. Man kann nur versuchen ein Gesamtsystem so zu gestalten, dass die letzte Instanz so klein wie möglich ist und dafür sorgt, das selbst im schlimmsten Fall keine Daten zerstört werden. So eine Sicherheit ist wiederum nur mit modular aufgebauten Systemen erreichbar, sei es auf Betriebssystem-, Datenbank- oder Anwendungsebene.
Warum diese Blogeintrag? Wir hatten grade so einen Fehler. Ab und an (extrem selten) ist uns die umfangreiche und mit Eigenintelligenz ausgestattete Adresserfassung abgestürzt. Es gab zwar niemals eine Datenzerstörung, aber der Absturz an sich ist einfach ärgerlich für den Kunden, denn die Adresse muss neu erfasst werden. Da der Fehler so selten aufgetreten ist, und der tatsächliche Absturz in keinem Zusammenhang mehr mit dem ursprünglichen Fehler stand, hat es wirklich gedauert, bis der Fehler gefunden wurde, denn welcher Anwender ist schon in der Lage 100%ig zu beschreiben, was er genau eingegeben hat. Wie dem auch sei, wir haben’s gelöst und sind wieder etwas schlauer.

Anmerkung:
Es gibt diverse Verfahren wie Code Coverage und andere, die in dieser Konstellation jedoch nicht weiterhelfen…

Dieser Beitrag wurde unter Programmieren an sich abgelegt und mit verschlagwortet. Setze ein Lesezeichen auf den Permalink.

2 Kommentare zu Mit Intelligenten Fehlermanagement kann man sich in den Fuß schießen

  1. Farid sagt:

    Toller Artikel. Kann nicht schaden, sich mit dem Thema im detail zu beschaeftigen. Werde sicher weitere Artikel im Auge behalten.

  2. akoppel sagt:

    Im Laufe der letzten Jahre haben wir stetig hinzugelernt (so ist das halt immer in der Softwareentwicklung). Wenn man C-Programme schreibt, so ist der ungültige Zeigerzugriff ein Klassiker. Richtig kompliziert wird’s halt bei Multithreading-Anwendungen, da kann es schon mal passieren, dass man an irgend einer Stelle nicht aufpasst und von einem Thread auf einen Zeiger zugegriffen wird, der von einem anderen Thread freigegeben wurde. Sicherlicht sollte das bei einer sauberen Programmierung nicht passieren (Semaphore und Mutexe helfen), aber es passiert denoch. Die Komplexität entsteht ja gerade dadurch, dass das Zeitverhalten von Threads bei Abhängigkeiten zu anderen „Sachen“ wie Datenbanken und I/O leider nicht deterministisch ist. Der Anwender erwartet jedoch ein Feedback so schnell wie möglich. In dieser Gesamtkomplexität – Performance auch dort zu erzeugen, wo man keinen Einfluss hat – entstehen genau die oben geschilderten Probleme.
    Wir sind dazu übergegangen, dass wir unter Verwendung der Systembibliotheken die Speicherbereiche überprüfen, bevor wir darauf zugreifen, das machen wir immer dann, wenn die Gefahr besteht, dass ein Speicherbereich mittlerweile ungültig geworden ist. Es hat gut ein Jahr gedauert, bis wir das performant hinbekommen haben.

Schreibe einen Kommentar

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