9 comments

[ 3.8 ms ] story [ 42.8 ms ] thread
The Heisenbug: a software bug that seems to disappear or alter its behavior when one attempts to study it.[0] They're rare, but they do happen.

[0] https://en.wikipedia.org/wiki/Heisenbug

My favorite, which I unfortunately never dug into enough (/don't remember the solution), was a bug in some horrible pile of Javascript that only raised an exception _if the developer console was open in the browser_. So on a normal refresh, everything goes fine, but as soon as you open the console to diagnose or inspect something else, bam, now you've got _two_ issues...
LOL, my current favorite is the one where our site session dies once the Dev Tools are opened in IE11 (but only on Windows 10). It makes debugging a serious pain.

(Yes, we’re still supporting it for some reason)

I do think among the most common bugs is the increased understanding of the problem domain.

Code often does what it is intended to do, but the result is wrong because the problem wasn't actually sufficiently understood when the solution was formulated.

If you have a function that for a given integer N returns a value m=f(N) so that m²=N, and you run the function and get positive m:s on weekdays and negative m:s on weekends (on x86, the happens opposite on ARM), we're quick to say that's a bug.

No, it's just a surprise.

The function works as advertised, that f(N) would be identical to sqrt(N) is just an assumption you made that isn't found in the specs. The requirements never said anything about the sign of m, that's a requirement you added retroactively when it wasn't behaving as you expected.

I think this is very often the case with the experience of those "how can this have ever worked"-bugs. You were never surprised by the behavior because you never examined it particularly closely before.

That is exactly my argument against Test Driven Development.
I'm not sure it's that scathing. Tests may well be seen as a tool for granting access to a particular piece of logic and allow you to interact with it it directly, to ensure that the code remains sufficiently decoupled to allow this. In that case, they may aid in discovering and examining unexpected behavior.

This isn't waterproof though. I think TDD-code prima facie upholds its promise to keeping down the code complexity per module, this is often at the expense of the bigger picture architecture. You go from spaghetti code to ravioli code; hardly an improvement.

> memcpy(arr + i, arr + i + 1, (num_items - i) * sizeof(*arr));

Appropriately enough, this line contains a bug.

(comment deleted)