Rubber duck debugging is a well known debugging technique – it boils down to explaining the code to a rubber duck, whether a real one, or a coworker who unwittingly becomes the “rubber duck”. Halfway through the explanation the “Wait … what?” moment pops up, you know where the bug is and you run off to fix it, potentially leaving your coworker wondering why you just ran off mid-sentence.
There are plenty of articles that talk about rubber duck debugging in detail, but why should this neat technique be restricted to just debugging? I’ll explore one area in particular – applying this technique as a means to improve existing code and design, rather than just for debugging.
The mighty duck
Rubber duck debugging requires you to you walk through your code and explain it step by step, justifying what each bit of code is meant to do and how it is doing it. At some point you end up realizing that what you thought the code ought to do and what the code actually does don’t actually match, and that could be the bug!
Or maybe you misunderstood something. This may be an opportunity to improve your code, by adding a test, cleaning up a comment, or refactoring your code, so that next time you walk through the code the logic is more self-evident (as a side-note – I’m a big fan of self-documenting code which significantly reduces the chance that your comments become a lie as your code changes, among other things).
OK, cool, so that’s mostly just good ol’ rubber duck debugging… so what? I think that the same approach can be applied more broadly, specifically in the context of improving existing code and designs. The idea is the same as before, you walk through your code / design, explaining what it does and how to your rubber duck of choice, and through this process you find opportunities to make things better. I alluded to that in the previous paragraph, where you’d be looking for a bug, but may find things along the way that could be improved. However, unlike regular debugging where you basically have to find and fix the bug, pragmatically, when would it be sensible to do such a walk-through?
Applying to code? Maybe
The initial inclination may be that this isn’t worth the trouble at all, and, for majority of the cases pertaining to code, it’s probably right: code is often either good-enough to serve its purpose as is, might be relatively short-lived, or otherwise uninteresting… but there may be bits of code that are subtle, critical to the correctness / performance, or otherwise impor