Detective work for programs
Every programmer spends a large share of their time debugging, and beginners shouldn't read that as a sign of failure. Code rarely works perfectly on the first attempt. Debugging is the methodical part: notice something is wrong, reproduce it reliably, narrow down where it goes wrong, understand why, then fix it and confirm the fix holds.
The name is often linked to a moth found in a Harvard computer in 1947 and taped into a logbook as the "first actual case of bug being found." Engineers were calling defects "bugs" long before that, but the story stuck.
Tracking down a bug with print statements
The simplest technique is printing values to check your assumptions:
def total_price(items):
total = 0
for price in items:
total = price # bug: should be total += price
print("after", price, "total is", total)
return total
total_price([5, 10, 3])
The printed output shows total being replaced instead of growing, which points straight at the faulty line. For bigger problems, add breakpoint() in Python (or debugger; in JavaScript) to pause the program and inspect every variable at that moment.
Debugging vs testing
Testing tells you that something is broken. Debugging tells you why. A failing test is a great starting point, because it gives you a repeatable way to trigger the problem and to check the fix later.
A few habits help a lot:
- Read the full error message and stack trace. When an exception is raised, the trace lists the file and line where it happened.
- Change one thing at a time, so you know which change mattered.
- Explain the code aloud, line by line. Talking it through (the "rubber duck" method) often exposes a wrong assumption.
Learn more
Last updated