Skip to content

guide

Rubber Duck Debugging: Why Explaining Code to a Toy Actually Works

What Is Rubber Duck Debugging Rubber duck debugging is explaining your code line-by-line to an inanimate object until you spot the bug yourself. The listener…

· 7 min read

A developer desk with a laptop, notebook and space for a desk toy

Devs At Home is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program. We earn from qualifying purchases. This never affects what we recommend or what we say about it.

What Is Rubber Duck Debugging

Rubber duck debugging is explaining your code line-by-line to an inanimate object until you spot the bug yourself. The listener doesn't need to understand programming. Doesn't need to be a rubber duck, either. A cardboard box works. So does a potted plant.

The method appeared in The Pragmatic Programmer in 1999, where Andrew Hunt and David Thomas described a programmer who carried a rubber duck and debugged by talking to it. The duck never answered. That was the point.

You explain what the code is supposed to do, then what it actually does, line by line. Usually you find the problem before you finish. Verbalising forces you to examine assumptions you didn't know you were making.

Why Rubber Duck Debugging Works

Your internal monologue runs faster than you can speak. Read code silently and you skip over the parts that seem obvious. You fill in gaps. You see what you expect, not what's there.

Speech slows you down. You have to finish each sentence. You can't skim a for-loop when you're saying it — "this iterates from zero to length minus one" — and then you hear yourself say "length minus one" and realise length is off by one.

The constraint is cognitive, not auditory. Typing your explanation in a chat window to yourself works nearly as well. Anything that forces serial processing instead of the parallel assumptions your brain makes when reading code you wrote does it. Pair programming achieves the same result, but rubber ducking doesn't require another person's time. You can do it at two in the morning.

The Articulation Gap

The bug lives in the space between what you think the code does and what you can actually say it does. If you can't explain a function clearly, you don't understand it clearly. The duck makes that visible.

Variables named temp or data are fine when you're thinking fast. Then you say out loud "I set temp to the value of data" and notice you've lost track of what temp represents. Renaming it usually fixes two other bugs you hadn't noticed yet.

This is why the method works even though the duck doesn't respond. You're not looking for advice. You're looking for the friction between your mental model and the code that's actually running.

When to Use Rubber Ducking Programming

Use it when you've been staring at the same twenty lines for fifteen minutes. When you've added print statements and the output makes no sense. When the bug is clearly right there but you can't see it.

Logic errors respond best — off-by-one, wrong variable, inverted condition, bad assumption about input. Environment issues, race conditions and anything involving infrastructure you don't control? Less useful.

You don't need an actual duck. A coffee mug works. A monitor works. A coworker's back if they're wearing headphones. The object is a focal point, something to direct your explanation toward instead of staring at the screen.

Before You Ask Someone Else

Rubber duck first. Still don't find it after explaining the code out loud? Then ask a person. You'll ask a better question because you've already articulated the problem, so they'll spend less time getting oriented and more time actually helping.

Open-source projects and developer communities expect this. Explaining your debugging process in the question shows you've done the work. The act of writing that explanation often leads you to close the issue before posting it.

How to Rubber Duck Debug Effectively

Start before the bug. Explain what the function is supposed to do, in plain sentences. If you can't manage that without looking at the code, you're debugging from an unclear specification.

Then go line by line. Say what each line does and why it's there. Don't paraphrase. The code says i < array.length, you say "while i is less than array length" not "while there are items left." The bug lives in the gap between those two.

When you hit the bug, keep going. Explain the next five lines anyway. Sometimes the problem sits three lines down from where you think it is, or there's a second bug waiting to surface once you fix the first.

What to Say

Describe data flow, not syntax. "This takes the user input and splits it on commas" gets you further than "this calls the split method with comma as the argument." You're surfacing assumptions, not reading the code aloud word for word.

Name the types. "This returns a string." "This array contains user objects." Type mismatches hide in dynamic languages, and saying the type out loud exposes the problem immediately.

If you hear yourself saying "this probably" or "I think this," stop. That's the assumption. Verify it. Print statement or debugger — check whether what you think is happening is actually happening.

Common Mistakes

Skipping the "obvious" parts defeats the method. The bug is in the obvious part. That's why you can't see it. Skip lines you wrote today if you must, but explain everything older than that.

The other failure mode is summarising instead of articulating. "This loop processes the data" doesn't force you to think. "This loop starts at index one, not zero, and iterates to the length of the input array" makes you notice you're skipping the first element. One of those sentences does work; the other doesn't.

Explaining to a person too soon wastes their time and yours. You haven't tried the duck yet. You're asking them to be your working memory instead of using the method that doesn't require coordination.

When It Doesn't Work

You've explained the code twice and still don't see it. The problem is probably not in the code you're looking at. Check the function that calls this one. Check what data it's receiving. Check whether the bug is in your mental model of what the system does, not in this specific function.

Take a break. Make coffee. The solution shows up in the shower because your brain stops actively searching and switches modes. Rubber ducking is a structured version of that mode switch. Sometimes you need the actual break.

Variations and Alternatives

Writing the explanation instead of speaking it works nearly as well. Open a scratch file and type what each function does and why. Some developers keep a debugging journal — a text file where they explain the problem before they start fixing it. Once the explanation is written, fixing is often unnecessary.

Teaching someone else achieves the same cognitive shift. If you're onboarding a junior developer, have them sit with you while you work through a bug. You'll spot mistakes you wouldn't have noticed alone, and explaining your process helps both of you.

Diagramming the data flow on paper serves a similar purpose. Draw boxes and arrows showing what data goes where. Converting code to a diagram forces the same kind of serial, explicit processing that speaking does.

Pair Programming vs Rubber Ducking

Pair programming provides a real person who might catch things you miss. It also requires coordinating schedules and maintains constant social overhead. Rubber ducking is available immediately and costs nothing but time.

Use pairs for complex architectural decisions or unfamiliar territory where another perspective helps. The duck is for implementation bugs where you know the domain but lost track of the details.

Does It Work for Non-Developers

Explaining a problem out loud works in any domain where complexity hides errors. Writers talk through plot holes. Designers walk through interface flows to spot inconsistencies. Accountants read spreadsheet formulas aloud to find mistakes.

The method itself is domain-agnostic. Expertise makes you skip steps mentally, and those skipped steps often contain the error. Code either works or doesn't, with no middle state, so the debugging process is more explicit — which is why you see it more among programmers. Not because it only works for them.

If you build mental models to solve problems, rubber ducking forces you to externalise those models. Then you can inspect them. The duck itself is optional. The externalisation is not.

Should You Actually Buy a Rubber Duck

You don't need one. Any object works. But plenty of developers keep a duck on the desk anyway because it signals to coworkers that you're debugging and shouldn't be interrupted. It's a physical indicator of mental state.

Some teams buy ducks for the whole group. It becomes shorthand: "I'm going to duck this" means "I'm going to think it through before asking for help." The shared language makes debugging less frustrating because there's an explicit step between "I'm stuck" and "I need someone else."

If you want one, get the cheapest rubber duck you can find. The four-dollar ones from a toy store work exactly as well as the twenty-dollar programmer-themed ones. It's going to sit on your desk collecting dust either way. Spend the saved sixteen dollars on better coffee.

One email a week

New reviews, teardowns and the occasional deal worth knowing about. No spam, unsubscribe any time.