Script Valley
Debugging: A Systematic Approach
Reading Code to Find BugsLesson 2.4

How to do a code review to find bugs before running code

static code reading, checklist-driven review, assumption identification, precondition checks, defensive reading

Code Review as Bug Finding

You do not need to run code to find bugs in it. A structured reading process -- treating review as adversarial rather than approving -- finds more bugs per minute than running tests during early development.

Defensive Reading

For every function, ask these questions in sequence: What are the preconditions -- what must be true for this function to work correctly? Are those preconditions enforced? What happens if each argument is null, undefined, empty, or the wrong type? What are all the exit paths, including implicit ones (missing return)? Does every code path return a value of the same type?

// Reading this defensively:
function getUserAge(userId) {
  const user = db.find(userId);
  return user.birthDate
    ? new Date() - new Date(user.birthDate)
    : 0;
}
// Q1: What if db.find returns null? user.birthDate throws TypeError
// Q2: The subtraction returns milliseconds, not years -- wrong unit
// Q3: birthDate could be a malformed string -- new Date(invalid) = NaN
// All bugs found without running the code

Assumption Hunting

Every line of code embeds assumptions. arr[0] assumes the array is non-empty. user.name assumes user is not null. parseInt(input) assumes input is a valid numeric string. Circle every assumption as you read. Each unchecked assumption is a potential bug.

Up next

How to use git blame and git log to find when a bug was introduced

Sign in to track progress