Besseres 'printf'-Debugging
Andere Sprachen: English Español Français 日本語 한국어 Português 中文
Eine der häufigsten Debugging-Techniken, das ‘printf’-Debugging, ist besonders beliebt, weil die meisten Menschen es intuitiv lernen, wenn sie ihre ersten Programme schreiben.
‘printf’-Debugging ist sehr zugänglich, da man keine speziellen Werkzeuge dafür benötigt. Wenn man sich mit seinen ersten Bugs auseinandersetzt, noch bevor man weiß, was ein Debugger ist, kommt es einem natürlich in den Sinn, das Programm Variablen Schritt für Schritt ausgeben zu lassen, damit man die Ausführung in der Konsole verfolgen kann.
Obwohl es eine der grundlegendsten Debugging-Techniken ist, nutzen auch erfahrene Entwickler sie häufig. Sie kann bei der Untersuchung jeder Art von Problemen helfen, wie suboptimale Routinen, inkonsistenter Zustand, Multithreading-Probleme und mehr.
Wie bereits erwähnt, erfordert diese Technik keine speziellen Werkzeuge wie eine IDE. Wenn man jedoch eine verwendet, kann sie die Effizienz beim Protokollieren des Programmzustands noch weiter steigern.
Dieser Artikel zeigt Funktionen von IntelliJ IDEA. Ähnliche Funktionen können in anderen IDEs vorhanden sein oder auch nicht. Wenn du ein anderes Werkzeug verwendest, solltest du dessen Dokumentation konsultieren, um zu sehen, ob diese Funktionen dort ebenfalls vorhanden sind.
Live Templates
IntelliJ IDEA bietet Live Templates für die gängigsten Debug-Logging-Muster. Um ein Live Template für Debug-Logging zu verwenden, gib die entsprechende Abkürzung ein und drücke Tab. IntelliJ IDEA generiert die Print-Anweisung und fügt sie an der Cursorposition ein.
Schauen wir uns ein paar Beispiele an.
Methodenparameter protokollieren
public static BufferedImage recolor(BufferedImage in, BufferedImage mask, int newColor) {
// type 'soutp' here, then press Tab
return null;
} public static BufferedImage recolor(BufferedImage in, BufferedImage mask, int newColor) {
System.out.println("in = " + in + ", mask = " + mask + ", newColor = " + newColor);
return null;
} Werte protokollieren
public static double coolMethod(double parameter) {
double a = Math.random();
double b = Math.random();
// type 'soutv' here, press Tab, then select the value
return a * b * parameter;
} public static double coolMethod(double parameter) {
double a = Math.random();
double b = Math.random();
System.out.println("b = " + b);
return a * b * parameter;
} Methodenaufrufe protokollieren
public static BufferedImage recolor(BufferedImage in, BufferedImage mask, int newColor) {
// type 'soutm' here, then press Tab
return null;
} public static BufferedImage recolor(BufferedImage in, BufferedImage mask, int newColor) {
System.out.println("ImageUtils.recolor");
return null;
} Logging-Breakpoints
Einer der Nachteile beim Debugging mit Print-Anweisungen ist, dass sie den Aufwand der manuellen Verwaltung mit sich bringen. Man kann sie nicht schnell ein- und ausschalten, und man möchte sie definitiv nicht versehentlich committen und in der Produktion ausführen.
Aus diesem Grund würde ich empfehlen, Logging-Breakpoints zu verwenden, wenn du etwas zu Debugging-Zwecken protokollieren musst, da sie viel einfacher zu verwalten sind.
Um einen Logging-Breakpoint zu setzen, halte Shift gedrückt und klicke dann in den Randbereich. Im Gegensatz zu einem regulären Breakpoint hält er die Programmausführung nicht an, sondern gibt stattdessen in die Konsole aus.
Standardmäßig ist es eine Meldung, die besagt, dass das Programm diese Zeile erreicht hat. Du kannst auch die Optionen neben dem Kontrollkästchen Evaluate and log in den Breakpoint-Einstellungen verwenden, wenn du lieber den aktuellen Stack-Trace oder das Ergebnis eines benutzerdefinierten Ausdrucks protokollieren möchtest.
Sei vorsichtig mit Logging-Ausdrücken. Das Auswerten von Ausdrücken, die Seiteneffekte verursachen, kann eine Quelle neuer Bugs oder unerwarteten Verhaltens sein. Außerdem können sie bei der Verwendung in häufig ausgeführtem Code dein Programm erheblich verlangsamen.
Wenn Logging-Breakpoints zahlreich werden, kannst du sie im Dialog Breakpoints (Run | View Breakpoints) verfolgen und verwalten:
Du kannst sogar benutzerdefinierte Gruppen für sie erstellen:
Dies hilft dir, deine Breakpoints zentral zu verwalten. Zum Beispiel kannst du eine Gruppe erstellen, die sich auf einen bestimmten Bug bezieht, und sie für später speichern. Wenn das Problem verschwindet, schalte sie einfach aus. Sollte das Problem wieder auftreten, musst du nicht alles von Grund auf neu erstellen. Du schaltest die Gruppe einfach wieder ein.
Häufige Ereignisse protokollieren
Bei Ereignissen, die während der Programmausführung häufig auftreten, kann das Protokollieren jedes einzelnen Ereignisses überflüssig sein. Dies überflutet nicht nur die Konsole mit Nachrichten, sondern viel Interaktion mit I/O kann auch die Debugging-Sitzung erheblich verlangsamen.
Für solche Ereignisse kann es nützlich sein, die Funktion Pass count zu verwenden. Du kannst darauf im Dialog Breakpoints zugreifen.
Nachdem du Pass count auf einen bestimmten Wert gesetzt hast, wird der entsprechende Breakpoint nur bei jedem n-ten Treffer ausgelöst, wodurch sichergestellt wird, dass das Logging nicht zum Ärgernis wird.
Zusammenfassung
Unabhängig davon, ob du Print-Anweisungen einfügst oder Logging-Breakpoints zum Debugging setzt, moderne Werkzeuge bieten Funktionen, um deine Debugging-Erfahrung zu verbessern. Mit diesem Beitrag wollte ich sicherstellen, dass du diese kleinen Tricks kennst, die den gesamten Prozess angenehmer gestalten.
Viel Erfolg beim Debugging!