Skip to content

◎ Developing Debugging Skills Over Time


◎ Debugging Is a Skill That Grows

Unlike syntax rules — which can be learned in a day — debugging competence develops over months and years of deliberate practice. There is no shortcut and no ceiling.

This does not mean progress is slow. It means that every bug encountered is an opportunity to build something that no tutorial can provide directly: pattern recognition, system intuition, and the accumulated confidence that comes from having solved hard problems before.

On expertise and experience

Research into expert and novice debuggers found that experts and novices employed similar strategies — but experts simply formed more correct hypotheses and found bugs faster. The researchers suspected this was due to the difference in programming experience between the two groups.1

In other words: experts are not faster because they use different techniques. They are faster because they have seen more bugs, made more hypotheses, and built a larger library of patterns to draw on.

The research that produced this finding also identified five categories of knowledge that together constitute debugging competence. Julia Evans' reframing of these categories1 provides one of the most practical frameworks available for understanding how to improve deliberately.


◎ I. The Five Categories of Debugging Knowledge

Category I — System Knowledge (Codebase)

What it is: Understanding the specific codebase you are working in — how it is structured, what the components do, how they interact, where the known problem areas are.

Why it matters: You cannot debug code you do not understand. This may seem obvious, but it has a non-obvious implication: every debugging session in an unfamiliar part of the codebase is simultaneously a debugging task and a learning task. The time invested in understanding the code is not overhead — it is the work.

How to develop it:

  • Read code — not just your own, but the code around it, the code that calls it, and the code it calls
  • Trace execution paths through unfamiliar code before assuming you understand them
  • Treat debugging sessions in unfamiliar areas as forced tutorials on how that part of the system works
  • Document what you learn: architecture notes, method purposes, non-obvious relationships

Debugging is one of the best ways to learn a new codebase

When joining a new team or project, debugging an existing bug — rather than only reading documentation — forces you to trace actual execution paths, see how data flows, and understand how components interact in practice. The system reveals itself under the conditions of failure in ways that documentation rarely captures.


Category II — System / Domain Knowledge

What it is: Understanding the broader technical environment your application operates in — the language runtime, the platform, the networking layer, the database, the framework lifecycle, and the system-level behaviours that your code depends on.

Why it matters: Many bugs that appear to be in your code are actually caused by the behaviour of the system beneath your code. A NullPointerException may be caused by a lifecycle method being called in the wrong order. A wrong calculation may be caused by integer overflow in the underlying runtime. A network timeout may be caused by a default timeout that no configuration overrides.

The InfoWorld debugging guide2 puts it well: "Gain a good understanding of the system one level down from what you are working on. In many cases, error messages come from that one level down. If you can understand what that means, it will help you figure out what is going wrong at your level of abstraction."

How to develop it:

  • When a framework behaves unexpectedly, read its documentation thoroughly — not just the "getting started" guide, but the reference documentation for the specific feature
  • Study the lifecycle of the platforms you use: Android Activity and Fragment lifecycle, React component lifecycle, ASP.NET request pipeline
  • Learn how HTTP, databases, and network protocols work at a conceptual level — even if you are not building those layers yourself
  • When a system-level error message appears, look it up even if you already know the fix — understanding what the message means builds vocabulary for future encounters

Category III — Tool Knowledge (Procedural)

What it is: Knowing your debugging tools — how to use the IDE debugger, how to read Logcat or the console, how to write effective log statements, how to use git bisect, how to run static analysis, how to read a profiler output.

Why it matters: Tools make evidence visible. A programmer who does not know how to set a conditional breakpoint will spend an hour stepping through a loop that a conditional breakpoint would have bypassed in seconds. A programmer who does not know how to filter Logcat will read through hundreds of irrelevant lines to find the one that matters.

The investment in learning tools pays compound returns. The time spent understanding the debugger once is recovered across hundreds of future debugging sessions.

How to develop it:

  • In each new project or on each new platform, commit to learning at least one debugger feature you have not used before
  • Read the documentation for your IDE's debugging features — most developers use a fraction of what is available
  • Practise with the tools deliberately — not only when debugging, but as a learning exercise
  • Learn keyboard shortcuts for the operations you use most often; the friction of reaching for a mouse slows the investigative rhythm

A practical learning commitment

If you have never used a conditional breakpoint, set one today on any code you are working on — even if you do not need it for a current bug. Create a condition, run in debug mode, and observe the behaviour. The time cost is five minutes. The return is that conditional breakpoints become available to you as a tool the next time you genuinely need one.


Category IV — Strategic Knowledge

What it is: The heuristics, patterns, and approaches you have developed for debugging efficiently — the mental shortcuts and investigative strategies that experienced programmers accumulate over time.

Why it matters: Strategic knowledge is what allows an experienced programmer to look at an error message, a symptom pattern, or a set of circumstances and immediately form a plausible hypothesis — without working through every possibility from scratch. It is the difference between a systematic search and a targeted search.

Examples of strategic knowledge:

  • "If it works the first time but fails on subsequent calls, check whether state is being reset correctly between calls."
  • "If the error only occurs in production, check configuration and environment variables first."
  • "If a null pointer exception appears deep in framework code, trace back to the last method in your code in the stack trace."
  • "If a calculation is correct for small inputs but wrong for large ones, check for integer overflow."
  • "If it was working yesterday and nothing obvious changed, check git log for recent commits."

How to develop it:

  • After every significant bug, ask the three explanation questions: Why did it fail? What assumption was wrong? Why does the fix work? The answers are raw material for strategic knowledge.
  • Read post-mortems — both your own and those published by engineering organisations. Each one describes a real failure mode and the reasoning that resolved it.
  • When you encounter a pattern for the second time, recognise it explicitly: "I have seen this before. It was caused by X."
  • Pay attention to the bugs that took longest to find. Those are the ones where your strategic knowledge was weakest — and where adding the new pattern has the highest value.

Category V — Experiential Knowledge

What it is: The accumulated pattern recognition that comes from having investigated many bugs across many codebases and systems over time.

Why it matters: This is the category that separates programmers who have been practising for ten years from those who have been practising for one year — not because the ten-year programmer has read more documentation, but because they have encountered more failure modes, formed more hypotheses, and built a larger library of patterns that activate on recognition.

On the value of experience

"I've had SO MANY bugs that were really frustrating and difficult the first time I ran into them, and very straightforward the fifth or tenth or twentieth time."1

This is the nature of experiential knowledge. The first NullPointerException from an uninitialised view costs an hour. The twentieth costs thirty seconds — not because the programmer applies a different technique, but because the pattern is immediately recognised.

How to develop it:

  • Investigate bugs — all of them, including the small ones. Every bug is a data point.
  • Do not skip the explanation step. A bug that is fixed without being understood does not add to experiential knowledge.
  • Debug other people's code. The bugs in someone else's code are harder to find (you do not have the author's assumptions), and harder problems build stronger pattern libraries. The InfoWorld guide2 specifically recommends this: "Debug other people's code rather than your own. It will be easier to see the faults in the other person's assumptions than it is to see your own."
  • Review your own old code periodically. Seeing the mistakes you made six months ago — and being able to identify them quickly — is direct evidence of skill growth.

◎ II. Improving Deliberately by Level

If you are at the foundational level (◉)

Focus on System Knowledge (understanding the code you are currently writing) and Tool Knowledge (learning your IDE's basic debugger features). These two categories give you the most immediate return at this level.

Specific actions:

  • After every bug: write one sentence explaining the root cause. Not just the fix — the cause.
  • This week: learn to set a line breakpoint and step through a method in your IDE.
  • This month: read the documentation for one language feature you have been using without fully understanding.

If you are at the investigative level (◈)

Focus on Strategic Knowledge (building patterns from the bugs you encounter) and extending System / Domain Knowledge (understanding the platforms and frameworks you are working in).

Specific actions:

  • Keep a brief debugging log — a note for each significant bug with the symptom, root cause, and fix. Review it monthly.
  • After each investigation: identify the point where you were most stuck. What would have resolved it faster? Is there a tool, a technique, or a piece of knowledge that would have helped?
  • Read one post-mortem from a published engineering blog this month. Notice the reasoning structure.

If you are at the strategic level (◆)

Focus on Experiential Knowledge (deliberately exposing yourself to a wider range of failure modes) and Strategic Knowledge (formalising the patterns you have already observed).

Specific actions:

  • Volunteer to investigate bugs in parts of the codebase you do not own. The unfamiliarity is the exercise.
  • Write a post-mortem after every significant bug, even if it is only for your own records.
  • Mentor a junior colleague through a debugging session — the discipline of explaining your reasoning makes it explicit.
  • Read the documentation for a debugging tool you have never used. Profile something. Try git bisect on a real codebase.

◎ III. The Compounding Effect

Debugging skill is one of the few technical skills where the returns genuinely compound. Each bug investigated builds pattern recognition that makes the next bug faster to diagnose. Each tool learned reduces the friction between a hypothesis and the evidence needed to test it. Each explanation written converts a one-time fix into reusable knowledge.

The programmers who debug fastest are not those who read the most tutorials. They are those who have investigated the most bugs, explained each one to themselves, and built the largest library of patterns to draw on.

There is no shortcut. But the work is the practice — and the practice is the job.


You have completed 04 · Tools, Techniques & Thinking.

Continue to: 05 · Appendices →

← Back to: Section Index



  1. Discussed and reframed by Julia Evans — "A Way to Categorise Debugging Skills" — https://jvns.ca/blog/2022/08/30/a-way-to-categorize-debugging-skills/ 

  2. InfoWorld — "Learning and Improving Your Debugging Skills" — https://www.infoworld.com/article/2164328/learning-and-improving-your-debugging-skills.html