Wie kann man Code am effektivsten debuggen? [geschlossen]

33

Fehler, die sich in Code einschleichen, können minimiert, aber nicht vollständig beseitigt werden - Programmierer sind, obwohl viele anderer Meinung sind , nur Menschen.

Was können wir tun, um einen Fehler in unserem Code auszumerzen, wenn wir ihn entdecken? Wie sollten wir vorgehen, um unsere wertvolle Zeit optimal zu nutzen und weniger Zeit für die Suche und mehr Zeit für die Codierung zu verwenden? Was sollten wir auch beim Debuggen vermeiden?

Beachten Sie, dass wir hier nicht über das Verhindern von Fehlern sprechen . wir reden über das, was zu tun ist, wenn Fehler Sie erscheinen. Ich weiß, dass dies ein weites Feld ist und in hohem Maße von Sprache, Plattform und Tools abhängt. Wenn ja, halten Sie sich an umfassende Antworten wie Denkweisen und allgemeine Methoden.

gablin
quelle
Verknüpfte Frage wurde entfernt.
1
Ich denke, der Ansatz ist eigentlich einfach. Wenn Sie es alleine entwickelt haben, wissen Sie alles darüber. Sie können den Fehler sogar beheben, ohne ihn zu debuggen. In diesem Sinne ist der beste Weg, Ihre Zeit zu verwenden, um etwas anderes zu codieren, bis jemand, der viel darüber weiß, Ihre Frage beantworten kann, wie man es behebt. oder, lass es ruhen, codiere andere Dinge, bis dir die Idee einfällt, es zu reparieren, damit du weder Zeit noch Energie verlierst. Ich vermute, Ihre Frage bezieht sich auf das Management von Unternehmensteams.
Aquarius Power
Ich denke, Raid. Ab Lager, Insektenspray. Ist das eine philosophische Frage? Bücher werden aus dem bloßen Übergewicht gemacht ...
Ejbytes

Antworten:

38

Die Denkweise und Einstellung zum Debuggen ist vielleicht der wichtigste Teil, da sie bestimmt, wie effektiv Sie den Fehler beheben und was Sie daraus lernen - wenn überhaupt.

Klassiker der Softwareentwicklung wie The Pragmatic Programmer und Code Complete vertreten grundsätzlich den gleichen Ansatz: Jeder Fehler ist eine Gelegenheit, fast immer über sich selbst zu lernen (weil nur Anfänger den Compiler / Computer zuerst beschuldigen).

Behandle es also als ein Mysterium, das interessant zu knacken sein wird. Und dieses Rätsel sollte systematisch gelöst werden, indem wir unsere Annahmen (uns selbst oder anderen gegenüber) zum Ausdruck bringen und dann, wenn nötig, nacheinander unsere Annahmen testen - mit jedem uns zur Verfügung stehenden Tool, insbesondere Debuggern und automatisierten Test-Frameworks. Nachdem Sie das Rätsel gelöst haben, können Sie noch bessere Ergebnisse erzielen, indem Sie Ihren gesamten Code nach ähnlichen Fehlern durchsuchen, die Sie möglicherweise gemacht haben. und schreiben Sie einen automatisierten Test, um sicherzustellen, dass der Fehler nicht unwissentlich erneut auftritt.

Ein letzter Hinweis: Ich nenne Fehler lieber "Fehler" und nicht "Bugs". Dijkstra warf seinen Kollegen vor, den letzteren Begriff zu verwenden, weil er unehrlich ist. Ich schaue nicht, anstatt wegen unseres eigenen (schlampigen) Denkens da zu sein: http://www.cs.utexas.edu/users/EWD/transcriptions/EWD10xx/EWD1036.html

Wir könnten zum Beispiel damit beginnen, unsere Sprache zu bereinigen, indem wir einen Fehler nicht länger als Fehler, sondern als Fehler bezeichnen. Es ist viel ehrlicher, weil es die Schuld genau dorthin legt, wo es hingehört, nämlich. mit dem Programmierer, der den Fehler gemacht hat. Die animistische Metapher des Fehlers, der sich böswillig eingeschlichen hat, während der Programmierer nicht hingeschaut hat, ist intellektuell unehrlich, da sie verschleiert, dass der Fehler die eigene Schöpfung des Programmierers ist. Das Schöne an dieser einfachen Vokabeländerung ist, dass sie so tief greifend wirkt: Während früher ein Programm mit nur einem Fehler "fast korrekt" war, ist später ein Programm mit einem Fehler einfach "falsch" (weil in Error).

Limist
quelle
7
Eigentlich mag ich den Begriff "Fehler" lieber als "Fehler", nicht weil "der Programmierer, der den Fehler gemacht hat" die Schuld trägt, sondern weil klar wird, dass es möglicherweise nicht der Programmierer war, der den Fehler gemacht hat. Für mich bedeutet "Fehler" einen Fehler im Code. wohingegen "Fehler" irgendwo einen Fehler impliziert . Vielleicht im Code, vielleicht im Setup der Umgebung, vielleicht in den Anforderungen. Macht mich verrückt, wenn mein Chef eine "Fehlerliste" hat, in der sich die Hälfte der Probleme auf Änderungen der Anforderungen bezieht. Nennen wir es eine Aufgabenliste, Ferchrissakes!
Carson63000
2
+1 für "Jeder Fehler ist eine Gelegenheit zu lernen, fast immer über sich selbst (weil nur Anfänger den Compiler / Computer zuerst beschuldigen)"
Md Mahbubur Rahman
Sie kennen die Geschichte des Begriffs "Bug", oder? Ich meine, wie in der Softwareentwicklung verwendet. Natürlich haben wir dieses Problem heute nicht, aber tatsächlich ist ein Fehler in die Hardware eines Computers geflogen, der vom Programmierer unbemerkt blieb und ein Problem verursachte. Damit mich nicht jemand korrigieren kann, weiß ich, dass Edison diesen Begriff lange vor dem Mottenvorfall verwendet hat. Deshalb habe ich das Wort "Geschichte" und nicht "Ursprung" verwendet. Siehe computerworld.com/article/2515435/app-development/… und en.wikipedia.org/wiki/Software_bug#Etymology
threed
Natürlich. Seit geraumer Zeit verursachen Insekten jedoch nicht mehr die meisten Softwarefehler.
Limist
16
  1. Schreibe Tests. Testen ist nicht nur großartig, um Bugs zu verhindern (meiner Erfahrung nach beseitigt TDD alle trivialen, dummen Bugs), sondern hilft auch beim Debuggen. Das Testen erzwingt ein eher modulares Design, wodurch das Isolieren und Replizieren des Problems erheblich vereinfacht wird. Außerdem kontrollieren Sie die Umgebung, sodass es weniger Überraschungen gibt. Wenn Sie einen fehlerhaften Testfall erhalten, können Sie außerdem ziemlich sicher sein, dass Sie den wahren Grund für das Verhalten gefunden haben, das Sie stört.

  2. Erfahren Sie, wie Sie einen Debugger verwenden. printAnweisungen funktionieren auf einer bestimmten Ebene recht gut, aber ein Debugger ist die meiste Zeit sehr hilfreich (und sobald Sie wissen, wie man es verwendet, ist es viel komfortabler als printAnweisungen).

  3. Sprechen Sie über jemanden über Ihr Problem, auch wenn es sich nur um ein Gummiente handelt . Sich zu zwingen, das Problem, an dem Sie arbeiten, in Worten auszudrücken, ist wirklich ein Wunder.

  4. Geben Sie sich ein Zeitlimit. Wenn Sie zum Beispiel nach 45 Minuten das Gefühl haben, Sie gehen nirgendwo hin, wechseln Sie für einige Zeit zu anderen Aufgaben. Wenn Sie zu Ihrem Fehler zurückkehren, werden Sie hoffentlich andere mögliche Lösungen sehen können, die Sie vorher nicht in Betracht gezogen hätten.

Ryszard Szopa
quelle
2
+1 für "Sich zu zwingen, das Problem, an dem Sie arbeiten, in Worten auszudrücken, tut wirklich Wunder."
Md Mahbubur Rahman
Und um (1) hinzuzufügen, impliziert fast jeder Fehler, den Sie im Code sehen, dass die Testsuite einen Fehler - oder zumindest eine Lücke - enthält. Beides gleichzeitig beheben - Sie beweisen nicht nur, dass Sie das Problem behoben haben, sondern sind auch sicher, dass es nicht wieder eingeführt wird.
Julia Hayward
3

Ich denke, die Reproduktion eines Fehlers ist auch wichtig. Alle Fälle, die den Fehler reproduzieren, können aufgelistet werden. Anschließend können Sie sicherstellen, dass Ihre Fehlerbehebung alle diese Fälle abdeckt.

aslisabanci
quelle
3

Zu diesem Thema gibt es ein ausgezeichnetes Buch mit dem Titel " Why Programs Fail" , in dem verschiedene Strategien zum Auffinden von Fehlern beschrieben werden, die von der Anwendung der wissenschaftlichen Methode zum Isolieren und Beheben eines Fehlers bis zum Delta-Debugging reichen. Der andere interessante Teil dieses Buches ist, dass der Begriff "Fehler" wegfällt. Zellers Ansatz ist:

(1) Ein Programmierer erzeugt einen Fehler im Code. (2) Der Defekt verursacht eine Infektion. (3) Die Infektion breitet sich aus. (4) Die Infektion verursacht einen Fehler.

Wenn Sie Ihre Debug-Fähigkeiten verbessern möchten, empfehle ich dieses Buch.

Aus eigener Erfahrung habe ich viele Fehler in unserer Anwendung gefunden, aber das Management drängt uns einfach weiter, um neue Funktionen herauszubringen. Ich habe oft gehört "Wir haben diesen Fehler selbst gefunden und der Kunde hat es noch nicht bemerkt, also lass es einfach, bis sie es tun". Ich denke, dass es eine sehr schlechte Idee ist, reaktiv zu sein, anstatt Fehler proaktiv zu beheben, da es an der Zeit ist, eine Lösung zu finden, andere Probleme gelöst werden müssen und die Verwaltung weiterer Funktionen so schnell wie möglich aus dem Haus gehen soll, damit Sie erwischt werden in einem Teufelskreis, der zu viel Stress und Burnout und letztendlich zu einem Systemdefekt führen kann.

Kommunikation ist auch ein weiterer Faktor, wenn Fehler gefunden werden. Das Versenden einer E-Mail oder das Dokumentieren im Bug-Tracker ist in Ordnung, aber nach meiner Erfahrung finden andere Entwickler einen ähnlichen Fehler und verwenden die Lösung, die Sie zur Behebung des Codes eingesetzt haben, nicht erneut (da sie alles vergessen haben) ), sie fügen ihre eigenen Versionen hinzu, so dass Sie 5 verschiedene Lösungen in Ihrem Code haben und es dadurch aufgeblähter und verwirrender aussieht. Wenn Sie also einen Fehler beheben, sollten Sie sicherstellen, dass einige Personen den Fehler überprüfen und Ihnen Feedback geben, falls sie etwas Ähnliches behoben und eine gute Strategie gefunden haben, um damit umzugehen.

limist erwähnte das Buch The Pragmatic Programmer, das einige interessante Informationen zur Behebung von Fehlern enthält. Anhand des Beispiels, das ich im vorigen Absatz gegeben habe, würde ich Folgendes betrachten: Software Entrophy , wobei die Analogie einer zerbrochenen Witwe verwendet wird. Wenn zwei viele zerbrochene Fenster angezeigt werden, ist Ihr Team möglicherweise nicht mehr in der Lage, diese zu reparieren, es sei denn, Sie nehmen eine proaktive Haltung ein.

Trostloser Planet
quelle
Ich habe gehört "Wir haben diesen Fehler selbst gefunden und der Kunde hat ihn noch nicht bemerkt, also lass es einfach, bis er es tut", auch zu oft. Und Besuche vor Ort gegangen, oft der Kunde hat bemerkt, aber es ist nicht berichtet. Manchmal, weil sie denken, dass es keinen Grund gibt, weil es nicht behoben werden kann, manchmal, weil sie bereits einen Ersatz für einen Konkurrenten suchen, und manchmal (zu Recht oder zu Unrecht) "nun, es ist sowieso alles ein dampfender Haufen Mist".
Julia Hayward
@ Julia Hayward - Dies ist sehr oft der Fall, aber in Ihrer Situation können Ihre Kunden mit der Funktionalität zufrieden sein und sich nicht zu sehr darum kümmern, was unter der Haube vor sich geht. Das Problem tritt auf, wenn der Client nach zusätzlichen Funktionen fragt und Sie weitere Verbesserungen hinzufügen müssen, z. B. die Mehrsprachigkeit Ihrer App und die Kompatibilität mit Mobilgeräten.
Desolate Planet
Nur zeigt Ihnen, alle Bücher der Welt über Software-Design, Tests und gute Kommunikation und viele der Produkte, an denen Sie arbeiten, sind ein riesiges Durcheinander. Trotz des Wissens, was richtig ist, sind Stress und unrealistische Fristen (angesichts Ihres bereits durcheinandergebrachten Codes) die Gründe, warum der Code in dem Zustand ist, in dem er ist. Ich selbst habe keine Antwort darauf. Ich bin im Büro als stöhnendes Gesicht ausgezeichnet, während ich trete und schreie, um den Code gesund und den Entwicklungsprozess reibungslos zu halten, aber manchmal tut das Team es nicht. t gut miteinander verbinden.
Desolate Planet
3

Fehler, Irrtum, Problem, Defekt - wie auch immer Sie es nennen möchten, es macht keinen großen Unterschied. Ich bleibe beim Problem, da ich es gewohnt bin.

  1. Finden Sie heraus, wie das Problem wahrgenommen wird: Übersetzen Sie von "Bob ist noch nicht im System" eines Kunden in "Wenn ich versuche, einen Benutzerdatensatz für Bob zu erstellen, schlägt dies mit einer Ausnahme für doppelte Schlüssel fehl, obwohl Bob dies noch nicht getan hat." da drin'
  2. Finden Sie heraus, ob es sich wirklich um ein Problem oder nur um ein Missverständnis handelt (tatsächlich ist Bob nicht dabei, es gibt niemanden namens Bob, und Insert sollte funktionieren).
  3. Versuchen Sie, minimale zuverlässige Schritte zu erhalten, die Sie befolgen können, um das Problem zu reproduzieren. Beispiel: "Wenn ein System mit einem Benutzerdatensatz" Bruce "angegeben wird und ein Benutzerdatensatz" Bob "eingefügt wird, tritt eine Ausnahme auf."
  4. Dies ist Ihr Test - wenn möglich, legen Sie ihn in ein automatisiertes Test-Harness, das Sie immer wieder ausführen können. Dies ist beim Debuggen von unschätzbarem Wert. Sie können es auch zu einem Teil Ihrer Testsuite machen, um sicherzustellen, dass dieses bestimmte Problem später nicht erneut auftritt.
  5. Holen Sie Ihren Debugger raus und beginnen Sie, Haltepunkte zu setzen. Ermitteln Sie den Codepfad, wenn Sie Ihren Test ausführen, und ermitteln Sie, was nicht stimmt. Währenddessen können Sie Ihren Test auch verfeinern, indem Sie ihn so eng wie möglich gestalten - idealerweise als Einheitentest.
  6. Beheben Sie das Problem - überprüfen Sie, ob Ihr Test bestanden wurde.
  7. Stellen Sie sicher, dass das vom Kunden beschriebene ursprüngliche Problem ebenfalls behoben ist (sehr wichtig - Sie haben möglicherweise nur eine Teilmenge des Problems behoben). Stellen Sie sicher, dass Sie keine Regressionen in anderen Aspekten des Programms eingeführt haben.

Wenn Sie mit dem Code sehr vertraut sind oder wenn das Problem oder die Lösung offensichtlich ist, können Sie einige dieser Schritte überspringen.

Wie sollten wir vorgehen, um unsere wertvolle Zeit optimal zu nutzen und weniger Zeit für die Suche und mehr Zeit für die Codierung zu verwenden?

Ich gehe davon aus, dass das Schreiben von neuem Code wertvoller ist als ein qualitativ hochwertiges Arbeitsprogramm. Es gibt nichts auszusetzen, wenn man Probleme so effektiv wie möglich behebt, aber ein Programm wird nicht unbedingt besser, wenn man einfach mehr Code hinzufügt.

ptyx
quelle
Dies ist die beste Antwort IMO
marcusshep
3

Ich mag die meisten anderen Antworten, aber hier sind einige Tipps, was zu tun ist, BEVOR Sie irgendetwas davon tun. Sparen Sie Zeit.

  1. Stellen Sie fest, ob wirklich ein Fehler vorliegt. Ein Fehler ist IMMER ein Unterschied zwischen Systemverhalten und Anforderungen. Der Tester sollte in der Lage sein, das erwartete und das tatsächliche Verhalten zu artikulieren. Wenn er nicht in der Lage ist, das erwartete Verhalten zu unterstützen, gibt es keine Anforderung und keinen Fehler - nur die Meinung von jemandem. Sende es zurück.

  2. Berücksichtigen Sie die Möglichkeit, dass das erwartete Verhalten falsch ist. Dies könnte auf eine Fehlinterpretation der Anforderung zurückzuführen sein. Dies kann auch auf einen Mangel in der Anforderung selbst zurückzuführen sein (ein Delta zwischen einer detaillierten Anforderung und einer Geschäftsanforderung). Sie können diese auch zurückschicken.

  3. Isolieren Sie das Problem. Nur die Erfahrung lehrt Sie den schnellsten Weg, dies zu tun - manche Leute können es fast mit ihrem Bauch tun. Ein grundlegender Ansatz besteht darin, eine Sache zu variieren, während alle anderen Dinge konstant bleiben (tritt das Problem in anderen Umgebungen auf? Mit anderen Browsern? In einer anderen Testregion? Zu verschiedenen Tageszeiten?) Fehlermeldungen - manchmal können Sie anhand der Formatierung feststellen, welche Komponente des Systems den ursprünglichen Fehler verursacht hat (z. B. können Sie dem Dritten, mit dem Sie in Berlin zusammenarbeiten, die Schuld geben, wenn er in deutscher Sprache verfasst ist).

  4. Wenn Sie es auf zwei Systeme eingegrenzt haben, die zusammenarbeiten, überprüfen Sie die Nachrichten zwischen den beiden Systemen über die Verkehrsüberwachung oder Protokolldateien und stellen Sie fest, welches System sich wie angegeben verhält und welches nicht. Wenn das Szenario mehr als zwei Systeme enthält, können Sie paarweise Überprüfungen durchführen und den Anwendungsstapel nach unten abarbeiten.

  5. Der Grund, warum das Eingrenzen des Problems so kritisch ist, besteht darin, dass das Problem möglicherweise nicht auf einem Codefehler beruht, über den Sie die Kontrolle haben (z. B. Systeme von Drittanbietern oder die Umgebung), und Sie möchten, dass diese Partei die Übernahme so schnell wie möglich durchführt . Das erspart Ihnen die Arbeit und bringt sie sofort auf den Punkt, sodass die Auflösung in einem möglichst kurzen Zeitraum erreicht werden kann. Sie möchten zehn Tage lang nicht an einem Problem arbeiten, nur um festzustellen, dass es sich wirklich um ein Problem mit dem Webservice eines anderen handelt.

  6. Wenn Sie festgestellt haben, dass es sich tatsächlich um einen Fehler handelt und der Code tatsächlich von Ihnen kontrolliert wird, können Sie das Problem weiter eingrenzen, indem Sie nach dem letzten "als funktionierend bekannten" Build suchen und die Versionsverwaltungsprotokolle auf Änderungen untersuchen, die das Problem möglicherweise verursacht haben. Dies kann viel Zeit sparen.

  7. Wenn Sie es nicht aus der Quellcodeverwaltung herausfinden können, ist es jetzt an der Zeit, Ihren Debugger anzuhängen und den Code durchzugehen, um es herauszufinden. Die Chancen stehen gut, dass Sie ohnehin eine ziemlich gute Vorstellung von dem Problem haben.

Wenn Sie wissen, wo sich der Fehler befindet, und sich eine Fehlerbehebung vorstellen können, gehen Sie folgendermaßen vor, um den Fehler zu beheben:

  1. Schreiben Sie einen Komponententest, der das Problem reproduziert und fehlschlägt.

  2. Lassen Sie den Komponententest bestehen, ohne ihn zu ändern (indem Sie den Anwendungscode ändern).

  3. Bewahren Sie den Komponententest in Ihrer Testsuite auf, um eine Regression zu verhindern bzw. zu erkennen.

John Wu
quelle
1

So mache ich es:

  1. Wenden Sie jedes Mal dieselbe Methode an, um das Problem zu finden. Dies verbessert Ihre Reaktionszeit auf die Fehler.
  2. Der beste Weg ist wahrscheinlich, den Code zu lesen. Dies liegt daran, dass alle Informationen im Code verfügbar sind. Sie brauchen nur effiziente Methoden, um die richtige Position zu finden und alle Details zu verstehen.
  3. Das Debuggen ist sehr langsam und nur erforderlich, wenn Ihre Programmierer noch nicht verstehen, wie der Computer asm-Anweisungen ausführt / Call Stacks und grundlegende Dinge nicht verstehen kann
  4. Versuchen Sie, Beweistechniken wie die Verwendung von Funktionsprototypen zu entwickeln, um das Verhalten des Programms zu beurteilen. So finden Sie schneller die richtige Position
tp1
quelle
1

Was können wir tun, um einen Fehler in unserem Code auszumerzen, wenn wir ihn entdecken? Wie sollten wir vorgehen, um unsere wertvolle Zeit optimal zu nutzen und weniger Zeit für die Suche und mehr Zeit für die Codierung zu verwenden? Was sollten wir auch beim Debuggen vermeiden?

Angenommen, Sie befinden sich in einer Produktionsumgebung, müssen Sie Folgendes tun:

  1. Beschreiben Sie den "Fehler" richtig und identifizieren Sie die Ereignisse, die ihn verursachen.

  2. Bestimmen Sie, ob der "Fehler" ein Codefehler oder ein Spezifikationsfehler ist. Beispielsweise kann die Eingabe eines Namens mit einem Buchstaben für einige Systeme als Fehler angesehen werden, für andere Systeme jedoch als akzeptables Verhalten. Manchmal meldete ein Benutzer einen Fehler, den er für ein Problem hält, aber die Erwartungen des Benutzers an das Verhalten des Systems waren nicht Teil der Anforderungen.

  3. Wenn Sie bewiesen haben, dass ein Fehler vorliegt und der Fehler auf den Code zurückzuführen ist, können Sie bestimmen, welche Codeteile repariert werden müssen, um den Fehler zu vermeiden. Untersuchen Sie auch die Auswirkungen des Verhaltens auf aktuelle Daten und zukünftige Systemoperationen (Auswirkungsanalyse auf Code und Daten).

  4. Zu diesem Zeitpunkt hätten Sie wahrscheinlich eine Schätzung, wie viel Ressourcen verbraucht werden, um den Fehler zu beheben. Sie können das Problem entweder sofort beheben oder einen Fix für eine bevorstehende Version der Software planen. Dies hängt auch davon ab, ob der Endbenutzer bereit ist, für das Update zu zahlen. Sie sollten auch verschiedene verfügbare Optionen auswerten, um den Fehler zu beheben. Es kann mehr als einen Weg geben. Sie müssen den Ansatz auswählen, der der Situation am besten entspricht.

  5. Analysieren Sie die Gründe, aus denen dieser Fehler aufgetreten ist (Anforderungen, Codierung, Tests usw.). Erzwingen Sie Prozesse, die verhindern, dass die Bedingung erneut auftritt.

  6. Dokumentieren Sie die Episode angemessen.

  7. Veröffentlichen Sie das Update (oder die neue Version)

Keine Chance
quelle