Ist das Drucken auf Konsole / Standard eine gute Debugging-Strategie?

10

Nehmen wir an, wir haben eine Funktion wie diese:

public void myStart()
{
    for (int i = 0; i<10; i++) myFunction(i); 
}


private int myFunction(int a)
{

    a = foo(a);
    a = bar(a);
    return a; 
}

private int foo(int a)
{
    //do something here

    //something gnarly here

    //etc
    return aValue;
}

private int bar(int a)
{
    // do something here
    //return aValue;
}

Aus irgendeinem Grund funktioniert unser Code nicht. Vielleicht wirft es einen Fehler, vielleicht gibt es den falschen Wert zurück, vielleicht steckt es in einer Endlosschleife fest.

Das erste, was ein Programmierer im ersten Jahr programmiert, ist das Drucken auf Konsole / Standard (nachdem er gelernt hat, wie man Hello World druckt, bevor er lernt, einen Debugger zu verwenden).

Zum Debuggen dieses Codes können sie beispielsweise Folgendes tun:

private int myFunction(int a)
{
    print("before foo: a=" + a); 
    a = foo(a);
    print("before bar: a=" + a);
    a = bar(a);

    return a; 
}

private int foo(int a)
{
    //do something here
    print ("foo step1: a=" + a); 

    //something gnarly here
    print ("foo step2: a=" + a + " someOtherValue="+ someOtherValue + " array.length= " + someArray.length()); 
    //etc
    return aValue;
}

private int bar(int a)
{
    // do something here
    //return aValue;
}

Jetzt führen sie den Code aus und erhalten einen großen Konsolendruck, mit dem sie nachverfolgen können, wo etwas schief geht.

Eine Alternative besteht natürlich darin, an jedem Punkt Haltepunkte zu setzen und den Code schrittweise durchzugehen.

Ein Hauptvorteil des Druckens auf der Konsole besteht darin, dass der Entwickler den Wertefluss auf einmal sehen kann, ohne durch Schritte usw. klicken zu müssen.

Der Nachteil ist jedoch, dass Ihr Code dann mit all diesen Druckanweisungen durchsetzt ist, die dann entfernt werden müssen.

(Ist es vielleicht möglich, den Debugger anzuweisen, nur bestimmte Werte in ein Protokoll auszudrucken? Die Haltepunkte können dann einfach hinzugefügt oder entfernt werden, ohne den Code tatsächlich zu ändern.)

Ich verwende immer noch den Konsolendruck als primäre Debugging-Methode. Ich frage mich, wie häufig / effektiv dies im Vergleich zu etwas anderem ist.

Dwjohnston
quelle
1
Sie müssen lernen, wie Sie einen Debugger verwenden und ein geeignetes Protokollierungsframework verwenden. Es macht Sie viel glücklicher als das Drucken auf der Konsole (das gibt es nicht immer).
7
Es ist wichtig zu lernen, wie man Debugger verwendet. Es gibt jedoch viele Situationen, in denen das printf-Debugging die einzige verfügbare Debugging-Methode ist.
Whatsisname

Antworten:

25

Druckanweisungen und Debugger schließen sich nicht gegenseitig aus. Es handelt sich lediglich um verschiedene Tools, die Ihnen zur Verfügung stehen, um Fehler zu lokalisieren / zu identifizieren. Es gibt diejenigen, die behaupten, dass sie niemals einen Debugger berühren, und es gibt diejenigen, die nirgendwo im Code, den sie schreiben, eine einzige Protokollierungs- / Druckanweisung haben. Mein Rat ist, dass Sie nicht in einer dieser Gruppen sein wollen.

Lernen Sie stattdessen die Verwendung der Protokollierung und einen Debugger. Mit der Erfahrung werden Sie (fast ohne darüber nachdenken zu müssen) das richtige Werkzeug auswählen und die Arbeit genau und effizient erledigen. Ohne Erfahrung wählen Sie manchmal eine über die andere aus, und vielleicht dauert es etwas länger, die Variablen zu durchsuchen oder Protokolldateien zu durchsuchen, aber das ist alles Teil des Lernprozesses.

Also, um Ihre spezifische Frage zu beantworten. Ja. Die Verwendung von Ausdrucken zur Verfolgung der Ausführung ist eine gute und weit verbreitete Debugging-Strategie. Jedoch...

Verwenden Sie anstelle von print-Anweisungen ein Protokollierungsframework. Protokollierungsframeworks haben ein Konzept für Protokollierungsebenen, sodass Sie eine ganze Reihe von Protokollnachrichten hinzufügen und für jede Ebene eine Ebene auswählen können. Wenn Ihre Anwendung unter normalen Bedingungen ausgeführt wird, lautet Ihre Stufe FEHLER oder WARNUNG, sodass nur wichtige Informationen gemeldet werden. Wenn Sie jedoch den Code verfolgen und den Ausführungsablauf verstehen müssen, können Sie den Logger in INFO oder DEBUG ändern. Alle "print" -Anweisungen, die Sie bereits im Code haben, geben jetzt zusätzliche Informationen aus.

Verwenden eines Protokollierungsframeworks ...

  1. Sie müssen nicht alle Ausdrucke löschen, nachdem Sie fertig sind.
  2. Die Ausdrucke, die Sie im Code belassen, können Ihnen oder anderen Entwicklern helfen, diesen Code in Zukunft zu debuggen
  3. Sie können diesen Code vor Ort debuggen, ohne ihn jedes Mal neu erstellen zu müssen, um die gelöschten Ausdrucke hinzuzufügen.
  4. Sie können Protokollierungsnachrichten an eine beliebige Stelle umleiten, nicht nur an eine Konsole. Sie könnten zu einer Datei, einem Syslog, einer Datenbank, einem Socket ... usw. Gehen

Update: Ich habe gerade am Ende bemerkt, dass Sie gefragt haben: "Ist es vielleicht möglich, den Debugger anzuweisen, nur bestimmte Werte in ein Protokoll auszudrucken?". Abhängig davon, welchen Debugger Sie verwenden. In vielen modernen Debuggern können Sie eine Aktion definieren, die aufgerufen werden soll, wenn ein Haltepunkt erreicht wird. In einigen Fällen (ich habe dies in VS und WinDbg getan) ist es möglich, "dies drucken und fortsetzen" anzugeben. Visual Studio nennt sie "Tracepoints" anstelle von "Breakpoints".

DXM
quelle
+1 für den ersten Absatz. Debugger und Protokolle lösen zwei sehr unterschiedliche Probleme.
Blrfl
1
Aber stimmen Sie nicht zu, dass das Belassen der Protokollanweisungen im Code es hässlich macht?
Dwjohnston
1
hängt davon ab, welche Art von Protokollanweisungen Sie an Ort und Stelle belassen. Ich habe gerade dieses gefunden und entfernt: "logger.error (" WHAT ")". Ansonsten behandle ich den Protokollierungscode genauso wie den Rest meines Codes. Formatieren Sie es, lassen Sie es schön aussehen und machen Sie es informativ. Ja, jede zweite Zeile mit einer Print-Anweisung zu bestreuen ist etwas zu viel, und manchmal musste ich darauf zurückgreifen. Im Allgemeinen ist es jedoch überhaupt nicht schlecht, 10 bis 20 Protokollanweisungen in der gesamten Datei zu haben (Dateien / Klassen haben eine angemessene Größe und sind nicht gigantisch).
DXM
Ich, dass in einige Protokoll Aussagen verlassen nützlich sein könnten, zum Beispiel , wenn Sie ein Produktionssystem haben Sie vielleicht verschiedene wichtige Variablen zu Anmeldung , da sie so gewohnt sind , wenn einige Fehler macht Sie auftauchen sehen sofort , was in der Produktion passiert Umgebung. Für den Kontext der Entwicklung scheint es jedoch chaotisch. Zum Beispiel schreiben Sie Ihre Parsing-Funktion und haben Ihren regulären Ausdruck nicht richtig verstanden. Sie geben also eine Reihe von Protokollanweisungen ein, um zu überprüfen, was los ist, und um es schließlich zu klären. Ich denke nicht, dass es einen Mehrwert für die
Zukunft darstellt
1
@Izkata: Das hängt alles von den Besonderheiten Ihres spezifischen Fehlers ab und davon, wie viel Protokollierung Ihr Code bereits leistet. Ich versuche zu vermitteln, dass es immer sinnvoll ist, Protokollierungsanweisungen auf verschiedenen Ebenen zu haben: ERR -> WARN ... -> DEBUG. Wenn Sie mehr für etwas sehr Spezifisches benötigen, fügen Sie auf jeden Fall print-Anweisungen hinzu. Aber meine Antwort an jemanden, der "print" als Protokollierungsanweisung verwendet, wird immer zu einem Framework wechseln und dieses verwenden.
DXM
3

Protokollierung / Drucken und Debugger sind komplementäre Techniken mit unterschiedlichen Stärken und Schwächen - am besten verwenden Sie beide. Aber insgesamt würde ich sagen, dass Debugger in den meisten Fällen das überlegene Werkzeug sind und zuerst verwendet werden sollten, wobei das Protokollieren / Drucken nur für die Dinge verwendet wird, in denen es tatsächlich besser ist.

Vorteile von Debuggern:

  • Sie können den gesamten Programmstatus überprüfen, nicht nur die Werte, die Sie im Voraus ausdrucken wollten. Dies kann den Debugging-Prozess massiv beschleunigen, indem der Rückkopplungszyklus auf weniger als eine Sekunde reduziert wird. Besonders wichtig, wenn es einige Zeit dauert, bis der Fehler erreicht ist.
  • Sie können sehen, woher Anrufe kamen, und sogar Werte im Stack-Trace überprüfen.
  • Sie können (bis zu einem gewissen Grad abhängig von der Sprache / Plattform) Debug-Code erstellen, den Sie nicht einfach ändern können, da Sie nur den kompilierten Binär- oder Byte-Code haben.

Vorteile der Protokollierung / des Druckens:

  • Es ist kein spezieller Debug-Build oder eine spezielle Debug-Konfiguration erforderlich. Es funktioniert immer.
  • Kann verwendet werden, um Fehler zu analysieren, die schwer zu reproduzieren sind und selten auftreten
  • Kann verwendet werden, um zeitabhängige Fehler zu analysieren, bei denen die durch einen Debugger verursachte Pause den Fehler leicht verschwinden lassen kann.
  • Bietet Ihnen permanente Informationen, die Sie nach Belieben analysieren können. Sie können an verschiedenen Stellen im Programmablauf zwischen den Ausgaben hin und her springen.
Michael Borgwardt
quelle
Ein weiterer Vorteil der Protokollierung besteht darin, dass Sie erst beim x-ten Durchlaufen Ihres Codes auf das Problem stoßen und wirklich einen Rückblick darauf verwenden können, wie Sie dorthin gekommen sind. Die meisten Debugger haben keine Umkehrschaltfläche, aber die Protokollierung der Werte, mit denen eine übergeordnete Funktion aufgerufen wurde, funktioniert und bringt Sie häufig zumindest einem kleinen reproduzierbaren Fall näher.
Christopher Creutzig
1

Das Drucken auf Standardausgabe kann beispielsweise eine gute Strategie zum Debuggen Ihres Codes sein

  • Ich verwende viele print-Anweisungen, um zu sehen, was in verschiedenen Ebenen meines Codes vor sich geht, insbesondere wenn ich den Fehler nicht vollständig verstehe

  • oder vielleicht enthält der Fehler keine detaillierten Informationen, die mich darauf hinweisen könnten, welcher Teil des Codes genau das Problem verursacht.

Wie auch immer Sie sich an das Debuggen von Tools gewöhnen müssen, es gibt viele, je nachdem, welche Sprache oder Plattform Sie verwenden.

Eine andere Methode ist die Protokollierung. Ich protokolliere ständig Fehler, wenn ich an Android-Anwendungen arbeite. Auch bei der Ausnahmebehandlung kann man leicht einen Stack-Trace oder eine Fehlermeldung der ausgelösten Ausnahme protokollieren.

Plaix
quelle
3
Dieser Beitrag ist ziemlich schwer zu lesen (Textwand). Hätten Sie etwas dagegen bearbeiten sie in eine bessere Form ing?
Mücke
Ich habe es ein bisschen lesbar gemacht. Entschuldigung für den vorherigen!
Plaix