Debugging is time consuming, especially when the bug occurs in somebody else’s code. This is why our development methodology is about detecting bugs before they fade away in the ocean of the code base. We have, in particular, introduced rep invariants as a means of guaranteeing the consistency of representations, thereby preventing subtle bugs to occur. In this post, we tell you a real story about a poor programmer whose time would have been saved if these invariants were checked thoroughly.
On some distant day, Neo stumbled upon a bug. He was implementing
A.a() (i.e. the method a of class
A). Neo was lost because his class relied on a class
B, which itself depended on a class
C, and so on… all these classes having been implemented by some anonymous (ex-)colleague.
Moreover, none of the implementations were trivial; spotting the cause of the bug was thus an tremendous challenge. Neo started using the debugger and found his way up to class
C. He then wrote 8 new test cases to gain some insight into the exact problem, which wasn’t obvious at all. His investigations led him to a deeper class
D, for which he also wrote 8 new test cases to further reduce the possible scope of the bug.
Finally he was able to catch the bug and quickly fix it. Yet in the end he spent half a day discovering the criminal method call chain and writing new test cases, although fixing the bug took him a few minutes.
How could this have been different?
Actually, the origin of the bug lied in some mutator method of class
D that raised an exception in a specific case. The rep invariant of the class was specified and checked at the end of every mutator, but unfortunately didn’t cover this case. Should it had been complete, the proper assertion in class
D would’ve been broken, giving Neo the exact location of the bug. Debugging time would’ve been reduced from half a day to a very small number of minutes.
In conclusion, writing good rep invariants is way worth the initial cost as it can make you avoid tons of hours of debugging. This is particularly true for rather complex representations, but it can be a lifesaver even in the simplest cases. We all know that not all bug come from complex code.
What was last time you had to track a bug down? How frustrating and time consuming was it? Do you think that reliable representation would have avoided it?