When playing chess, a good player will always have a short-term plan. Spend two or three moves trapping that knight. Pressure the opponent's rook to force a retreat. Explore that opportunity for a checkmate. Of course, the plan may have to be revised as your opponent reacts. But the important thing is to always have a plan in mind to try. It's okay if your plan is merely a vague direction rather than a step-by-step roadmap. Even stalling until your opponent gets impatient is sometimes an acceptable plan. But just don't move pieces around randomly hoping to stumble across something great. That's a surefire recipe for disaster.
Debugging is a bit friendlier than chess since no opponent is actively working against you. So the "move pieces around randomly hoping to stumble across something great" philosophy usually will work in debugging… eventually. But having a plan of attack when debugging will make the process faster and easier. The core of debugging involves keeping a logical mindset, so it's not difficult to use the scientific method when diagnosing bugs.
In this chapter, we'll discuss some techniques for creating debugging plans of attack. We'll look at some real-world bugs to see what plans worked for them, and we'll also examine methods for logically analyzing a system, even if you don't have the source code. But first, let's talk about something we'd like to avoid: brute-force debugging.