I would like to advocate designing code so that it is easier to debug. When write code, we thinking about many different things:

  1. What edge cases am I missing?
  2. How will this code perform?
  3. How readable is this code?
  4. etc.

But most programmers, even really good programmers, don’t think debugging while writing their code.

Here are a few tips:

  1. Use lots of explaining variables (http://c2.com/cgi/wiki?IntroduceExplainingVariable). You can easily change the value of the explaining variable under the debugger. You can inspect the value of the variable before it goes into the next function. 
  2. Don’t call multiple non-trivial functions from the same statement. If I have:

    Func1(Func2(Func3()));

    It becomes a pain in the butt to pick which function to step into. It is also difficult to inspect the return value, and change it if necessary.
  3. Don’t use IfFailGo(Func()). IfFailGo is fine, but divide it up into two statements:

    hr = Func();
    IfFailGo(hr);
  4. Prefer inline functions to macros. The C++ compiler doesn’t include macros in the PDBs, but inline functions are still there, and you can step into them or func eval them.
  5. Prefer enums to #defines or GUIDs. The debugger can give you the human comprehendible version of enums, but never #defines, and only sometimes GUIDs. Clearly sometimes you don’t have a choice, but if you do, enums are great.
  6. Use actual types instead of VOID*/cast