EMZETT.
Login

Debugging

In short: The systematic process of finding an error (bug) in a program, understanding its cause, and fixing it.

In more detail: Common techniques range from simple output for checking variable values to specialised debugger tools, which let you pause execution step by step and inspect the current state of all variables (breakpoints). Good test code and informative error messages significantly shorten the time debugging takes.

In Depth

The term “bug” for a program error goes back to an anecdote from the 1940s, when a moth literally caused a fault in an early computer — since then, “debugging” has become established as the term for fixing errors.

The most common debugging techniques, from simple to advanced:

  • Print debugging: inserting output (print(), console.log()) at strategic points in the code, to see what value a variable actually has at a specific point. Simple and universally applicable, but tedious for complex flows and has to be removed again afterwards.
  • Debugger with breakpoints: a specialised tool (usually integrated into the IDE) pauses program execution at a marked spot, without changing the code. You can then let it continue step by step and see live what value every variable currently has.
  • Logging: like print debugging, but permanently anchored in the code and with severity levels (DEBUG, INFO, WARNING, ERROR) — useful for being able to trace what a program did even in production, without having to add extra debug output for every issue.
  • Reading the stack trace: for an exception, the stack trace shows exactly at which line of code the error occurred AND via which chain of function calls the program got there — often the fastest route to the cause of the error, once you learn to read it correctly (usually top to bottom, the actual error spot in your own code often sits further up than library-internal calls).

A proven systematic approach is progressively narrowing down the problem: instead of randomly searching for the error in many places at once, the suspect area of code is narrowed down by bisection (similar to a binary search) — does the first half of the program work correctly? If yes, the error is in the second half, and the approach is repeated there.

Good, expressive code prevents problems in the first place: descriptive variable names, small, testable functions with clear responsibility, and precise error messages (that say exactly WHAT was expected and WHAT was actually received) drastically reduce the time needed for debugging at all — the best debugging strategy is ultimately to have as little to debug as possible.

See also: Errors, Exceptions