So verbessern Sie Ihre Fähigkeit, vorhandenen Code zu debuggen [closed]
29
Eine übliche Aufgabe in der Arbeitswelt ist es, mit vorhandenem, aber fehlerhaftem Code umzugehen. Was sind einige Tipps, um Ihre Fähigkeiten als Debugger zu verbessern?
Es ist oft verlockend zu sagen: "Oh, ich weiß, was dieses Stück Code tut, es ist in Ordnung." Tu das nicht. Testen Sie jede Annahme und gehen Sie alles sorgfältig durch.
+1. Absolut. Seien Sie darauf vorbereitet, erstaunt zu sein, wie einige der Dinge, von denen Sie dachten, sie würden Ihnen einen Streich spielen.
aufather
funktioniert bei mir :)
setzamora
3
Das Debuggen von fremdem Code ist eine enorme Zeitverschwendung, ein Killer für die Produktivität, aber so ist es nun mal. Das einzige Mal, wenn es wirklich Sinn macht, die Fehler anderer zu beheben, ist, wenn sie verschwunden sind. Was ich hasse, hasse, hasse es, von einem erfahrenen Programmierer einen objektiv beschissenen Code zu durchlaufen, dann eine Frage zu stellen, um rechtzeitig Fortschritte zu erzielen, und einen Vortrag über die Verbesserung meiner Fähigkeiten beim Erlernen der vorhandenen Codebasis zu erhalten. Anders als das Studium der Natur macht das Lösen von durch Menschen verursachten Fehlern kaum Spaß. Zumindest bekomme ich meine Antwort. Die umgekehrte Situation wird nicht passieren, weil ich einfach besser bin und weniger Fehler hinterlasse.
Job
1
@Job: ... okay? Wollten Sie diesen Kommentar vielleicht in dem Beitrag hinterlassen? :)
Adam Lear
Dies! Es ist dumm, einem kleinen Teil Ihres Codes blind zu vertrauen, wenn Sie ein seltsames Problem beheben und der Code in Ordnung zu sein scheint.
Dan,
7
Inkrementelles Testen .
Testen Sie Ihren Code zunächst anhand des kleinsten Moduls, das sich schrittweise nach oben bewegt. Auf diese Weise ist der Versuch, herauszufinden, wo genau das Problem liegen könnte, nicht zu stressig.
Es bedeutet auch, dass es weniger Code gleichzeitig beeinflusst, da Sie sich inkrementell bewegen. Manchmal hatte ich Probleme, bei denen ich etwas repariert habe und das dazu führte, dass viele andere Dinge kaputt gingen. Ich gebe meinem Chef dafür Anerkennung, da er mir dies beigebracht hat, als ich herumgespielt habe.
Teilen und Erobern ist ein guter Ansatz. Versuchen Sie, eine sichtbare Eingabe (Benutzereingabe / Netzwerkereignis ...) und Ausgabe (Protokoll, Ausgabe an Benutzer, ausgehende Netzwerknachricht ...) zu identifizieren, zwischen denen das Problem besteht. Versuchen Sie, Abdrücke an größeren Stellen oder an wichtigen Stellen dazwischen zu platzieren, und versuchen Sie, den Fehler im Code einzugrenzen.
Teilen und Erobern kann auch bei Regressionen über versionskontrollierten Code sehr gut funktionieren. Finden Sie zwei Builds - eines, bei dem es wie erwartet funktioniert, das andere mit der Regression. Verengen Sie den Abstand, bis Sie eine Reihe von Checkins als potenzielle Verdächtige haben.
Schreiben Sie anstelle des Binär-Bug-Chops Tests in das Formular
Gegeben...
Wann...
Erwarten von...
Um zu überprüfen, was Sie tatsächlich über die Funktionsweise der App wissen und was Sie für wahr halten.
Die meisten IDEs vereinfachen das Extrahieren von Methoden und das Generieren von xUnit-Teststubs. Nutzen Sie das.
Warum nicht Debugs besprühen? Denn nachdem Sie fertig sind, müssen Sie wahrscheinlich einen Großteil dieser Arbeit rückgängig machen und eine ganze Menge dieser Debugs löschen. Wenn Sie Tests schreiben, hilft Ihnen Ihr Debugging dabei, zukünftige Fehler zu verhindern und zu erkennen.
Absolutes Debuggen ist Kunst für sich, insbesondere das Debuggen von Code anderer Leute.
Gratzy
2
Wie andere gesagt haben - nimm nichts an. Dies gilt insbesondere dann, wenn Sie den Code geschrieben haben. Beim Debuggen von Code anderer ist die Wahrscheinlichkeit größer, dass Sie langsamer werden, weil der Code neu für Sie ist oder Sie dem Codierer nicht vertrauen. Wenn Sie Ihren eigenen Code debuggen, ist es zu einfach anzunehmen, dass Sie ihn richtig geschrieben haben.
Für den eigentlichen Prozess des Debuggens:
Schreiben Sie Komponententests, falls diese noch nicht existieren.
Fügen Sie die entsprechende Protokollierung hinzu, falls diese noch nicht vorhanden ist.
Dann benutze das Debuggen.
Hinzufügen der Komponententests und erstmaliges Protokollieren effizienter als bei Verwendung des Debuggers. Sie erhalten auch den zusätzlichen Vorteil, dass die Komponententests dazu beitragen, künftige Fehler zu vermeiden, und die Protokollierung hilft beim künftigen Debuggen von Sitzungen.
Prüfen Sie, ob Sie das Ergebnis genau bestimmen können, bevor Sie über einen kleinen Codeabschnitt gehen. Dies neigt dazu, im Angesicht davon zu fliegen, dass Sie nichts annehmen (was ich übrigens positiv bewertet habe).
Das mag trivial klingen, aber lernen Sie die Nuancen Ihres Debuggers und die Tastenkombinationen. Manchmal können Debugger langsam genug sein, dass Ihr Verstand sich wundert, wenn Sie durch das Programm treten. Wenn Sie mit der Maschine Schritt halten können und nicht mit der Maus herumfahren, kann dies hilfreich sein.
Wenn Sie während des Debuggens Code ändern können:
Überlegen Sie, ob Sie Vor- UND Nachbedingungen festlegen möchten. Manchmal können Sie dann anstelle von Code übergehen.
Wenn Sie Aussagen mit komplizierten Ausdrücken haben, denken Sie über etwas nach (einige mögen dies missbilligen, aber es funktioniert für mich).
mögen:
bool isLessThan5 = a < 5;
bool isGreaterThan10 = a > 10;
if ( isLessThan5 || isGreaterThan10 )
{
// more code here
}
anstatt:
if ( a < 5 || a > 10 )
{
// more code here
}
In den Fällen, in denen Sie aus irgendeinem Grund nicht alles debuggen können, lernen Sie, sich mit einem Kollegen "zu ducken". Manchmal bringt das Erklären Licht ins Dunkel. (ok, vielleicht ist das nicht genau in dem Fragenthema, aber ich denke, es ist nah genug, um eine Erwähnung zu rechtfertigen)
Das Benennen von Unterkonditionen erfordert einen weiteren Schritt, nämlich das Umgestalten der Namen, wenn Sie herausfinden, wozu die Bedingung dient. Es könnte sich herausstellen, if (tooCloseToHydrant || overTheBrink) { wenn Sie später mehr erfahren.
1
Zwei Dinge, die darauf beruhen, dass die meisten der letzten 22 Jahre damit verbracht wurden, Code zu pflegen, den andere geschrieben haben.
Verstehe die Arten von Fehlern, die du normalerweise schreibst.
Zum Beispiel bin ich ein sehr akribischer Programmierer. Sobald mein Code kompiliert ist, ist er normalerweise frei von trivialen Fehlern. Meine Bugs sind also eher seltsam komplizierte Dinge wie Thread-Deadlocks. Auf der anderen Seite habe ich einen Freund, der meistens triviale Fehler schreibt - Semikolons am Ende von C ++ für Schleifen, so dass die nächste Zeile nur einmal ausgeführt wird, so etwas.
Gehen Sie nicht davon aus, dass andere Leute die gleichen Fehler schreiben wie Sie.
Ich weiß nicht, wie oft ich Zeit damit verschwendet habe, die großen Debuggerpistolen herauszuholen, vorausgesetzt, ein Bug war meine Art von wirklich subtiler, seltsamer Sache, nur um meinen Freund über meine Schulter schauen zu lassen und zu sagen: "Hast du das Extra bemerkt? Semikolon?" Nach Jahren davon greife ich zum ersten Mal zu den trivialen, tief hängenden Früchten, wenn ich mir den Code anderer Leute ansehe.
Formatieren Sie den Code neu, um festzustellen, ob sich etwas bewegt?
@ Thorbjørn: Wenn ich den Code übernommen habe, mache ich das manchmal, um die Lesbarkeit zu verbessern, aber um keine Tippfehler zu finden. Interessante Idee!
Bob Murphy
Sie müssen es nicht festlegen, sondern sehen, was passiert. Ich kann dringend empfehlen, eine Richtlinie durchzusetzen, die eine Neuformatierung des Codes erfordert - am besten automatisch -, wenn er eingecheckt wird.
@ Thorbjørn: Das würde ich gerne machen. Was empfehlen Sie als Code "Prettifier"? Ich arbeite hauptsächlich unter Linux und Mac.
Bob Murphy
Ich verwende Eclipse, das an beiden Stellen verfügbar ist, und der Java-Editor verfügt über eine sogenannte Aktion "Speichern", mit der Sie festlegen können, was bei jedem Speichern der Datei geschehen soll. Hier besteht eine der Optionen darin, die Quelle zu formatieren. Wir sind ein kleines Team, deshalb habe ich nicht mehr untersucht. Erfahrene Teams ermöglichen das Festschreiben von Hooks in den Quellcodeverwaltungssystemen, sodass ein Quellcodewiderstand abgelehnt werden kann, wenn er falsch formatiert ist. Sehr effizient.
1
Kennen Sie Ihre Werkzeuge. Der Debugger von Visual Studio verfügt beispielsweise über eine großartige Funktion namens TracePoints , die Haltepunkten gleicht. Statt jedoch den Code anzuhalten, wird eine Trace-Anweisung in die Debug-Ausgabe eingefügt .
Es wird dringend empfohlen, Bücher zu lesen oder einen Kurs über die Verwendung Ihres Debuggers zu belegen. Ich nahm an einigen Kursen teil und las einige Bücher von John Robbins, die meine Effektivität als Debugger entscheidend beeinflussten.
Verstehen Sie funktional, was der Code versucht zu tun. Wenn Sie nicht das vollständige Bild kennen (alle Testfälle, die dieser Code bestehen muss), ist es schwierig, das Debugging ordnungsgemäß durchzuführen, ohne neue Fehler einzuführen
Schreiben Sie automatisierte Komponententests und andere Arten von Integrations- und Funktionstests.
Je automatisierter die Tests sind, desto weniger Zeit müssen Sie in einem Debugger verbringen.
Auch gutes Design - SOLIDE Prinzipien. Wenn Sie kleine, fokussierte Klassen schreiben und die Komposition der Vererbung vorziehen, die Duplizierung beseitigen usw., ist Ihr Code immer einfacher zu debuggen.
Ich finde, dass gut gestalteter Code einen anderen Satz von Fehlern produziert als Code, der nicht gut gestaltet ist. Im Allgemeinen führt gut gestalteter Code zu Fehlern, die leichter zu finden, zu reproduzieren und zu beheben sind.
Die Ausnahme (und es gibt immer eine) ist Multithreading-Code :-)
Wenn Sie den Fehler auf einen kleinen Bereich eingegrenzt haben, ihn aber immer noch nicht finden können, versuchen Sie es mit der Option "Code anzeigen + Assembly" Ihres Debuggers. Wissen Sie genug ASM, um zu sagen "es sollte eine Verzweigung hier geben" oder "warum kopiert es nur das niedrige Wort?" wird oft den Codierungsfehler lokalisieren.
Die Folien für das Buch sind online verfügbar, aber ich finde, dass das Buch selbst leichter zu lesen ist.
Das Buch soll Ihnen den Einstieg erleichtern und Sie dazu bringen, wissenschaftlicher über das Debuggen nachzudenken. Es ist jedoch kein Ersatz für das Üben. Möglicherweise müssen Sie 10 Jahre lang schreiben und debuggen, bevor Sie eine Verbesserung Ihrer Leistung in einer Größenordnung feststellen können. Ich kann mich noch gut an Sun erinnern, als Senior-Entwickler, die seit 30 Jahren für Unix programmieren, in wenigen Minuten obskure Multithreading- oder Parallel-Bugs finden. Erfahrung ist wichtig!
Antworten:
Nimm nichts an
Es ist oft verlockend zu sagen: "Oh, ich weiß, was dieses Stück Code tut, es ist in Ordnung." Tu das nicht. Testen Sie jede Annahme und gehen Sie alles sorgfältig durch.
quelle
Inkrementelles Testen .
Testen Sie Ihren Code zunächst anhand des kleinsten Moduls, das sich schrittweise nach oben bewegt. Auf diese Weise ist der Versuch, herauszufinden, wo genau das Problem liegen könnte, nicht zu stressig.
Es bedeutet auch, dass es weniger Code gleichzeitig beeinflusst, da Sie sich inkrementell bewegen. Manchmal hatte ich Probleme, bei denen ich etwas repariert habe und das dazu führte, dass viele andere Dinge kaputt gingen. Ich gebe meinem Chef dafür Anerkennung, da er mir dies beigebracht hat, als ich herumgespielt habe.
quelle
Teilen und Erobern ist ein guter Ansatz. Versuchen Sie, eine sichtbare Eingabe (Benutzereingabe / Netzwerkereignis ...) und Ausgabe (Protokoll, Ausgabe an Benutzer, ausgehende Netzwerknachricht ...) zu identifizieren, zwischen denen das Problem besteht. Versuchen Sie, Abdrücke an größeren Stellen oder an wichtigen Stellen dazwischen zu platzieren, und versuchen Sie, den Fehler im Code einzugrenzen.
Teilen und Erobern kann auch bei Regressionen über versionskontrollierten Code sehr gut funktionieren. Finden Sie zwei Builds - eines, bei dem es wie erwartet funktioniert, das andere mit der Regression. Verengen Sie den Abstand, bis Sie eine Reihe von Checkins als potenzielle Verdächtige haben.
quelle
Schreiben Sie anstelle des Binär-Bug-Chops Tests in das Formular
Um zu überprüfen, was Sie tatsächlich über die Funktionsweise der App wissen und was Sie für wahr halten.
Die meisten IDEs vereinfachen das Extrahieren von Methoden und das Generieren von xUnit-Teststubs. Nutzen Sie das.
Warum nicht Debugs besprühen? Denn nachdem Sie fertig sind, müssen Sie wahrscheinlich einen Großteil dieser Arbeit rückgängig machen und eine ganze Menge dieser Debugs löschen. Wenn Sie Tests schreiben, hilft Ihnen Ihr Debugging dabei, zukünftige Fehler zu verhindern und zu erkennen.
quelle
Debuggen Sie weiter. Wenn Sie viel debuggen, werden Sie sich verbessern.
quelle
Wie andere gesagt haben - nimm nichts an. Dies gilt insbesondere dann, wenn Sie den Code geschrieben haben. Beim Debuggen von Code anderer ist die Wahrscheinlichkeit größer, dass Sie langsamer werden, weil der Code neu für Sie ist oder Sie dem Codierer nicht vertrauen. Wenn Sie Ihren eigenen Code debuggen, ist es zu einfach anzunehmen, dass Sie ihn richtig geschrieben haben.
Für den eigentlichen Prozess des Debuggens:
Hinzufügen der Komponententests und erstmaliges Protokollieren effizienter als bei Verwendung des Debuggers. Sie erhalten auch den zusätzlichen Vorteil, dass die Komponententests dazu beitragen, künftige Fehler zu vermeiden, und die Protokollierung hilft beim künftigen Debuggen von Sitzungen.
quelle
Prüfen Sie, ob Sie das Ergebnis genau bestimmen können, bevor Sie über einen kleinen Codeabschnitt gehen. Dies neigt dazu, im Angesicht davon zu fliegen, dass Sie nichts annehmen (was ich übrigens positiv bewertet habe).
Das mag trivial klingen, aber lernen Sie die Nuancen Ihres Debuggers und die Tastenkombinationen. Manchmal können Debugger langsam genug sein, dass Ihr Verstand sich wundert, wenn Sie durch das Programm treten. Wenn Sie mit der Maschine Schritt halten können und nicht mit der Maus herumfahren, kann dies hilfreich sein.
Wenn Sie während des Debuggens Code ändern können:
mögen:
anstatt:
In den Fällen, in denen Sie aus irgendeinem Grund nicht alles debuggen können, lernen Sie, sich mit einem Kollegen "zu ducken". Manchmal bringt das Erklären Licht ins Dunkel. (ok, vielleicht ist das nicht genau in dem Fragenthema, aber ich denke, es ist nah genug, um eine Erwähnung zu rechtfertigen)
quelle
if (tooCloseToHydrant || overTheBrink) {
wenn Sie später mehr erfahren.Zwei Dinge, die darauf beruhen, dass die meisten der letzten 22 Jahre damit verbracht wurden, Code zu pflegen, den andere geschrieben haben.
Verstehe die Arten von Fehlern, die du normalerweise schreibst.
Zum Beispiel bin ich ein sehr akribischer Programmierer. Sobald mein Code kompiliert ist, ist er normalerweise frei von trivialen Fehlern. Meine Bugs sind also eher seltsam komplizierte Dinge wie Thread-Deadlocks. Auf der anderen Seite habe ich einen Freund, der meistens triviale Fehler schreibt - Semikolons am Ende von C ++ für Schleifen, so dass die nächste Zeile nur einmal ausgeführt wird, so etwas.
Gehen Sie nicht davon aus, dass andere Leute die gleichen Fehler schreiben wie Sie.
Ich weiß nicht, wie oft ich Zeit damit verschwendet habe, die großen Debuggerpistolen herauszuholen, vorausgesetzt, ein Bug war meine Art von wirklich subtiler, seltsamer Sache, nur um meinen Freund über meine Schulter schauen zu lassen und zu sagen: "Hast du das Extra bemerkt? Semikolon?" Nach Jahren davon greife ich zum ersten Mal zu den trivialen, tief hängenden Früchten, wenn ich mir den Code anderer Leute ansehe.
quelle
Kennen Sie Ihre Werkzeuge. Der Debugger von Visual Studio verfügt beispielsweise über eine großartige Funktion namens TracePoints , die Haltepunkten gleicht. Statt jedoch den Code anzuhalten, wird eine Trace-Anweisung in die Debug-Ausgabe eingefügt .
Es wird dringend empfohlen, Bücher zu lesen oder einen Kurs über die Verwendung Ihres Debuggers zu belegen. Ich nahm an einigen Kursen teil und las einige Bücher von John Robbins, die meine Effektivität als Debugger entscheidend beeinflussten.
quelle
Verstehen Sie funktional, was der Code versucht zu tun. Wenn Sie nicht das vollständige Bild kennen (alle Testfälle, die dieser Code bestehen muss), ist es schwierig, das Debugging ordnungsgemäß durchzuführen, ohne neue Fehler einzuführen
quelle
Schreiben Sie automatisierte Komponententests und andere Arten von Integrations- und Funktionstests.
Je automatisierter die Tests sind, desto weniger Zeit müssen Sie in einem Debugger verbringen.
Auch gutes Design - SOLIDE Prinzipien. Wenn Sie kleine, fokussierte Klassen schreiben und die Komposition der Vererbung vorziehen, die Duplizierung beseitigen usw., ist Ihr Code immer einfacher zu debuggen.
Ich finde, dass gut gestalteter Code einen anderen Satz von Fehlern produziert als Code, der nicht gut gestaltet ist. Im Allgemeinen führt gut gestalteter Code zu Fehlern, die leichter zu finden, zu reproduzieren und zu beheben sind.
Die Ausnahme (und es gibt immer eine) ist Multithreading-Code :-)
quelle
Wenn Sie den Fehler auf einen kleinen Bereich eingegrenzt haben, ihn aber immer noch nicht finden können, versuchen Sie es mit der Option "Code anzeigen + Assembly" Ihres Debuggers. Wissen Sie genug ASM, um zu sagen "es sollte eine Verzweigung hier geben" oder "warum kopiert es nur das niedrige Wort?" wird oft den Codierungsfehler lokalisieren.
quelle
Lesen Sie das sehr wertvolle Buch Why Programs Fail: Eine Anleitung zum systematischen Debuggen von Andreas Zeller. Es führt Sie in viele Techniken, Theorien und Werkzeuge ein, von denen einige auf dem neuesten Stand der Forschung sind.
Die Folien für das Buch sind online verfügbar, aber ich finde, dass das Buch selbst leichter zu lesen ist.
Das Buch soll Ihnen den Einstieg erleichtern und Sie dazu bringen, wissenschaftlicher über das Debuggen nachzudenken. Es ist jedoch kein Ersatz für das Üben. Möglicherweise müssen Sie 10 Jahre lang schreiben und debuggen, bevor Sie eine Verbesserung Ihrer Leistung in einer Größenordnung feststellen können. Ich kann mich noch gut an Sun erinnern, als Senior-Entwickler, die seit 30 Jahren für Unix programmieren, in wenigen Minuten obskure Multithreading- oder Parallel-Bugs finden. Erfahrung ist wichtig!
quelle