Quality Code 101: Debug It!

Don’t even think about releasing a piece of code, if you haven’t stepped through every line at least 50 times with a debugger.

What? Are you serious? But I have written so many unit tests!

It is true, unit tests are an important aspect of long-term code quality, but they are just not enough. When you write a unit test, it is too easy to become optimistic and be absolutely sure that certain parts of your code work[1].  It is easy to forget the internal workings of your code, and skip some edge cases, and unless you write and execute school like test suits[2], it is too easy to leave things out.

Is there a correct way to do it?

When you step through your code, stop before every line you execute, and try to think what you expect it to do. Execute the line and compare your result with the expected result. Work in several abstraction levels. Debug every line of the method you’ve written. When you think it is working fine, treat it as a black box and debug the methods that call it without stepping into it. Sometimes code that seem correct in one abstraction level, will turn out to be faulty when you examine it from another[3].

Hila, you are so smart! I’ve found a bug!

Why, thank you! *brushes off an imaginary hair from face and beams graciously*
Now turn it into a unit test. Why? Because the next thing you will fix will probably break your code again. Run your test, make sure it fails. Fix the bug, make sure the unit test passes.

Ok, my code looks like it is working now. Can I stop debugging?

Nope. Go ahead, run it again. You will find another bug.

Arrgh! This is so much work!

Too bad, writing quality code is what you are paid to do. If you don’t like it, I heard Walmart are recruiting now.

Isn’t it better to spend the time implementing cool new features and having my QA test the code?

No, from several reasons. They cannot do it as well as you can. Not because they are stupid, but because they don’t know your code as well as you do. In fact, even the future you cannot do it as well as you can. If you move to another task and postpone cleaning up after yourself until you get your inputs back from QA, you will definitely not remember all the little details of your implementation, and these bugs will be a lot harder and a lot more costly to solve. And finally – it is not the QA’s job to find these bugs, they have more important things to do, like making sure the whole system is functioning from the user’s perspective and testing the overall design and integration points. If they have to deal with the bugs you were too lazy to fix all day long, when will they have time to do the real work?

Trust me, step through your code (and wear sunscreen). Your QAs will thank you. Your future you will thank you. Your manager will thank you. Your users will thank you. I will personally thank you.  Your neighbor’s cat will…

Hila, can I ask you something?

Yes, yes, I am implementing a new subsystem now and I’m finding trillions of funky bugs by stepping through my code.
Now go away! I’ve just hit a breakpoint!

[1] How can they not work? you wrote them!
[2] Let’s face it, you don’t
[3] This is why we are debugging as well as writing unit tests!


6 thoughts on “Quality Code 101: Debug It!”

  1. Ah, the beautiful life of people how can use a debugger in their work… :-)

    Anyhow, if we are talking about White Box VS. Black Box testing – then I, for one, am in the opinion that the developers should consecrate on White Box testing and leave the Black Box testing to the Q.A. people to deal with. That is not to say that developers are completely exempt from Black Box testing (I know a developer how used to write code, see that it complies and just send it to Q.A. for testing – that’s not the way to do things), but they should be limited to the bare minimum.

    White Box testing, on the other hand, should be extensive (and usually by that fact alone should cover all of the Black Box testing required from developers). Of course, modulation, abstraction and all other sorts of good programming can help (if they are applicable, which is not always the case). That should involve checking the run-time behavior of the code (possibly using a debugger, but other tools are also important), code reviews (not just as the final step before approval), comparing the code against the design (which WILL lead to the known “I should have though but that earlier”) and so on.

    Doing a quick search lead to this nice article that I liked (It’s an IEEE! What’s not to like!):
    It makes many points (without enough justifications, but that seems intentionally), the relevant ones for this discussion is the importance of using multiple testing method and the superiority of White Box testing.

    1. Yes, Java is a language for the lazy ;)

      I would add that white box testing should translate to automated low-level black box testing (unit tests). It becomes important as the code gets old and needs refactoring, but no one risks doing that because there are no automated tests.

      And the article is nice, thanks :)

      1. If Java is a language for the lazy, then what is Perl (or Python for that matter)? Just a philosophical pondering.

        As for the automated Black Box testing, and specifically as a replacement for White Box testing… I was going to say ‘I don’t know’, but I really mean ‘I disagree’. For one, I don’t believe that any form of Black Box testing can truly replace White Box testing, regardless of how rigorously it’s done. Side effects are the obvious problem I can thing of. The other thing is that we could always write the “automated” testing right before we actually change the code (in fact, if memory serves there are tools that do just that). In other words, I don’t think that the risks would diminish significantly (and more important, I don’t think that they will be VIEWED any differently) if there were any Black Box testing ready. Now, we can go into why that is (and if it is justifiable) – but I don’t think that’s the point. The point is this: trying to come up with a “complete” (and it is never truly complete) set of Black Box testing that is anywhere close to the White Box testing is: 1. very hard. 2. suffers from crucial “real world” problem (since abstraction is almost never so complete that the surrounding environment is of no effect). 3. won’t really reduce the risks (and certainly not the observed risks).
        So, lots of work with little reward – and therefore should be avoided.

        Of course, in the more simplistic cases you might actually be able to pull this off. Than again, it is rarely the simple cases that cause the problems…

  2. Is ‘sunscreen’ a kind of debugging tool for some programming environment you are using? I must be missing some joke here.

    Anyway, there is a metric, ‘code coverage’, to describe unit tests, which encourages you to exercise every line of code in your tests. In this post you take it a step further and urge that we *test* every line, i.e. exercise it in every way we can think of in the tests.

    N.B. when reading some of your posts, by the time I get to the footnotes, they do not make sense any more. Please, either give more context in the footnotes, put them at the end of each paragraph, or write them in the body of the text. Or, better yet, skip them entirely, if they are not that important. Thanks.

    1. You are.

      I don’t like this kind of metrics. More often than not, they present an incentive to “cheat” the system and improve the metrics instead of doing the actual work they are meant to evaluate.

      You can just hover over the footnote link with your mouse and read the text in the tool tip.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s