Well theres:
- Google;
- Google;
- Google;
- Stackoverflow;
- Google;
- Google;
- Maybe a book if I have one.
Seriously, I started (hobby) programming in the 1980s and even into the mid 90s you had to know things and have a technical library. Then google came along and its easier to google something than it is to look up (bookmarked!) API documentation (google "java stringbuilder" will get me there faster than navigating will) let alone an actual book (electornic or paper).
Most problems you're trying to solve have been solved before. Many times.
The rest of debugging comes down to decomposition, possibly unit testing (which is related to decomposition) and verifying your assumptions.
by "decomposition", I mean that your solution is structured in such a way that small pieces can be individually tested and readily understood. If you have a 7000 line method you're (probably) doing something wrong.
Understanding what assumptions you've made is key too so you can verify them. For example, when I started with PHP I wrote a piece of code like this:
$fields = $_SESSION["fields"]; // $fields is an associative array
$fields["blah"] = "foo";
and I was scratching my head trying to figure out why it didn't work (the array wasn't being updated next time I queried $_SESSION). I came from a Java background where you might do this:
Map fields = (Map)httpSession.get("fields");
fields.put("blah", "foo");
and that would most definitely work. PHP however copies the array. A working solution is to use references:
$fields =& $_SESSION["fields"]; // $fields is an associative array
$fields["blah"] = "foo";
or simply:
$_SESSION["fields"]["blah"] = "foo";
The last thing I'll say about debugging and writing robust code in general is to understand the boundaries of your solution. By this I mean if you're implementing a linked list then the boundary conditions will revolve around when the list is empty.