Wie wir unsere Fehlerkultur debuggen

Wie wir unsere Fehlerkultur debuggen

11. Februar 2021

Matthias Lindstädt

Teil1: Fehlervermeidung in der Softwareentwicklung

In kaum einer anderen Disziplin sind das Vermeiden und das Korrigieren von Fehlern ein so präsentes Thema wie in der Softwareentwicklung. Dem sogenannten „Debugging“ werden in der Fachliteratur eigene Kapitel, wenn nicht sogar ganze Bücher gewidmet. Auch diverse Motto-Shirts für Informatiker greifen das Thema auf, wenn sie beispielswiese die „six stages of debugging“ präsentieren, angefangen beim ungläubigen „That can’t happen“ bis hin zum geläuterten „Oh, I see“.

Und so ist es nur vernünftig, sich als Unternehmen die Frage zu stellen: Wie gehen wir sinnvoll mit Fehlern um? Der folgende zweiteilige Blog-Beitrag soll Denkanstöße und Techniken vermitteln, wie man sich als Team einer mehrwertschaffenden Fehlerkultur nähert.

Fehler sind subjektiv und eine Frage der Perspektive

Zunächst einmal lässt sich feststellen, dass es gar nicht so leicht ist, den Begriff „Fehler“ eindeutig zu definieren. Grundsätzlich kann man sagen, dass dieser immer ein Ereignis beschreibt, das mit einer bestimmten Erwartungshaltung in Konflikt steht. Diese Erwartungshaltung ist jedoch eine Frage der Perspektive. Beispielsweise kann es möglich sein, dass die Funktionsweise einer Software sich aus Sicht einer Person als falsch darstellt, während eine zweite Person das Verhalten als erwartungsgemäß ansieht. Von daher ist es unabdingbar ein funktionierendes Anforderungsmanagement zu betreiben, in dessen Rahmen die Aufgaben für alle Verantwortlichen verständlich und ausreichend detailliert beschrieben werden. Der erste Schritt zur Fehlervermeidung besteht also darin, einen Konsens zu schaffen über das, was überhaupt als Fehlerfall angesehen wird. Positiv ausgedrückt bedeutet es, dass man Einigkeit erzielt und (schriftlich festhält!), wann eine Software-Komponente einwandfrei funktioniert.

Ein Bewusstsein darüber, dass Fehler niemals vollständig vermieden werden können, ist wichtig

Doch auch, wenn allen Beteiligten klar ist, was die Akzeptanzkriterien einer Anforderung sind bzw. was eine bestimmte Software-Komponente können soll, so lässt sich dadurch natürlich nicht garantieren, dass es nicht zum Fehlerfall kommt. Fehler lassen sich in keinem Bereich des Lebens vollständig vermeiden und so auch nicht in der Informatik. Dennoch ist das Bestreben eines Software-Entwicklers natürlich, die Fehleranfälligkeit von Anwendungen so gering wie möglich zu halten. Man spricht hier auch von der Robustheit einer Software. Gleichzeitig sollte man in seinen Prozessen und besonders auch in seinem Mindset Raum schaffen, um aus bereits gemachten Fehlern zu lernen.

Zwei Ansätze: Fehlervermeidung und das Lernen aus Fehlern

Da wir uns als Menschen also in Bezug auf das Machen von Fehlern in einem zirkulären Prozess befinden („Nach dem Fehler ist vor dem Fehler“), ergibt es Sinn, sich die beiden möglichen Stadien getrennt voneinander bewusst zu machen. Wir betrachten also die Situation, bevor es zum Fehler kommt und getrennt davon die Situation, nachdem der Fehler bereits passiert ist. Dadurch kommen wir zu zwei verschiedenen Hebeln, an denen wir ansetzen können. Der erste ist die Vermeidung von Fehlern und der zweite ist der Erkenntnisgewinn aus diesen.

Technische Möglichkeiten zur Fehlervermeidung ausschöpfen

Beim Thema Fehlervermeidung sind für mein Gefühl die meisten Developer-Teams mehr oder weniger gut aufgestellt – zumindest mit Blick auf den technischen Prozess. In der Regel beinhaltet das Programmieren im Team eine Code-Review nach dem Vier-Augen-Prinzip. Auch Tests auf einer Integrationsumgebung durch unabhängige Tester (und nicht durch den Entwickler selbst!) sind weitestgehend Standard. Bei zeitlich aufwendigen und regelmäßigen Testaufwänden durch menschliche Anwender sollte man unbedingt über automatisierte Testverfahren nachdenken. Auch der Nutzen bzw. die Notwendigkeit einer weiteren Testumgebung, die sich zwischen dem Integrations- und dem Produktiv-System befindet, wird oft unterschätzt.

Eine sogenannte Qualitätssicherungs-Umgebung (kurz oft QS oder vom englischen quality assurance environment abgeleitet, QA genannt) hat den Vorteil, dass kurz vor einem Release erneut alle Einzel-Implementierungen getestet werden, ohne dass zu diesem Zeitpunkt noch Bewegung im Code stattfindet. Wurde euch schon mal eine Funktionalität von einer anderen zerschossen, obwohl sie eigentlich einwandfrei funktioniert hat, getestet und auch abgenommen wurde? Wenn ja, dann solltet ihr vielleicht über eine QS nachdenken. An dieser Stelle möchte ich zudem auch nochmal den Hinweis geben, dass – statistisch gesehen – gilt: Je später ein Programmierfehler innerhalb des Entwicklungs-Prozesses gefunden wird, desto höher sind die durch den Fehler verursachten Kosten.

Fazit

Wir haben gesehen, es gibt also eine Vielzahl von Möglichkeiten, das Auftreten von Bugs einzudämmen. Und in einer Zeit von intelligenten On-the-fly-Compilern und komfortablem Java-Exception-Handling sollte man meinen, dass es den Developer von heute ganz gut getroffen hat. Doch wie bereits gesagt, müssen wir letztendlich der Tatsache ins Auge sehen, dass Fehler in der Softwareentwicklung niemals vollständig vermieden werden können. Selbst die ausgereiftesten Prozesse und Test-Mechanismen können nicht verhindern, dass früher oder später ein unerwartetes und ungewolltes Ereignis eintritt. Daher stellt sich die Frage: Wie gehen wir damit um? Wie lernen wir aus Fehlern, um dann dieses Wissen wiederum gezielt für die zukünftige Fehlervermeidung einsetzen zu können?

Um diese und weitere Fragen dreht sich der zweite Teil meines Blog-Beitrags, wenn ich auf das Thema „Lernen aus Fehlern in der Softwareentwicklung“ eingehe.