Chapter 3: Debugging During Coding


Overview

In Chapter 2, I laid the groundwork for the project-wide infrastructure needed to enable engineers to work more efficiently. In this chapter, we'll turn to what you need to do to make debugging easier while you're heavy in the coding battles. Most people refer to this process as defensive programming, but I like to think of it as something broader and deeper: proactive programming, or debugging during coding. To me, defensive programming is the error handling code that tells you an error occurred. Proactive programming tells you why the error occurred.

Coding defensively is only part of the battle of fixing and solving bugs. Engineers generally attempt to make the obvious defensive maneuvers—for example, verifying that a C++ pointer to a string isn't NULL—but they often don't take the extra step that proactive programming would require: checking that same parameter to see whether the memory is sufficient to hold the maximum string allowed. Proactive programming means doing everything possible to avoid ever having to use the debugger and instead making the code tell you where the problems are. The debugger can be one of the biggest time drains in the world, and the way to avoid it is to have the code tell you exactly when something isn't perfect. Whenever you type a line of code, you need to stop and look at what you're assuming is the good-case scenario and determine how you're going to verify that the case in question is exactly what the state will be every time you execute that line of code.

It's a simple fact: bugs don't just magically appear in code. The "secret" is that you and I put them in as we're writing the code, and those pesky bugs can come from myriad sources. They can be the result of a problem as critical as a design flaw in your application or as simple as a typographical error. Although some bugs are easy to fix, others are nearly impossible to solve without major rewrites. It would be nice to blame the bugs in your code on gremlins, but you need to accept the fact that you and your coworkers are the ones putting the bugs in the code. (If you're reading this book, it has to be mainly your coworkers putting the bugs in.)

Because you and the other developers are responsible for any bugs in the code, the issue becomes one of finding ways to create a system of checks and balances that lets you catch bugs as you go. I've always referred to this approach as "trust, but verify," which is Ronald Reagan's famous quote about how the United States was going to enforce one of the nuclear arms limitation treaties with the former Soviet Union. I trust that my colleagues and I will use my code correctly. To avoid bugs, however, I verify everything. I verify the data that others pass into my code, I verify my code's internal manipulations, I verify every assumption I make in my code, I verify data my code passes to others, and I verify data coming back from calls my code makes. If there's something to verify, I verify it. This obsessive verification is nothing personal against my coworkers, and I don't have any psychological problems (to speak of). It's just that I know where the bugs come from; I also know that you can't let anything by without checking it if you want to catch your bugs as early as you can.

Before we go any further, I need to stress one key tenet of my development philosophy: code quality is the sole responsibility of the development engineers, not the test engineers, technical writers, or managers. You and I are the ones writing, implementing, and fixing the code, so we're the only ones who can take meaningful measures to ensure the code we write is as bug free as possible.

As a consultant, one of the most surprising attitudes I encounter in many organizations is that developers should only develop and testers only test. The prevailing problem with this approach is that developers write a bunch of code and ever-so-briefly decide whether it executes the good condition before throwing it over the wall to the testers. It goes without saying that you're asking for schedule slippage as well as a poor quality product when developers don't take responsibility for testing their code.

In my opinion, a developer is a tester is a developer. I can't stress this enough: if a developer isn't spending at least 40 to 50 percent of his development time testing his code, he is not developing. A tester's job is to focus on issues such as fit and finish, stress testing, and performance testing. Finding a crash should be an extremely rare occurrence for a tester. If the code does crash, it reflects directly on the development engineer's competence. The key to developer testing is the unit test. Your goal is to execute as much of your code as possible to ensure that it doesn't crash and properly meets established specifications and requirements. Armed with solid unit test results, the test engineers can look for integration issues and systemwide test issues. We'll go over unit testing in detail in the section "Trust Yourself, but Verify (Unit Testing)" later in this chapter.




Debugging Applications for Microsoft. NET and Microsoft Windows
Debugging Applications for MicrosoftВ® .NET and Microsoft WindowsВ® (Pro-Developer)
ISBN: 0735615365
EAN: 2147483647
Year: 2003
Pages: 177
Authors: John Robbins

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net