Bugs in your programs
As we learn to code, one of the most frustrating experiences we can have is finding bugs in our code. The easiest to fix are syntax errors — your compiler or interpreter will simply tell you about syntax errors, and you can fix them.
The gnarliest bugs occur when our program doesn't behave as expected. There are no obvious errors, no exceptions being thrown, and no safety net. We have no idea where to begin. These are logic bugs.
Most of these bugs turn out to not be bugs in our code, but bugs in our thinking. Most programming is merely transcribing the program in our heads into code that can be executed by the machine. This is why we call them programming languages. They're languages for thinking about programs. We use english-esque languages because they're better at reasoning about logical programs than, say, assembly language.
Where syntax errors are either transcription errors (we've incompletely or inaccurately copied the program from our heads into the machine) or they're places where we aren't speaking the programming language correctly. The program could be correct in your head but expressed inaccurately in the language.
Logic bugs are much more subtle, since they indicate some building block we've been using behaves counter to our expectations.
Third party libraries are notorious spots for logic bugs. As a simple example, suppose we want to add OAuth to our web app. We will probably utilize a third party library. We'll read the documentation, integrating this library's behavior into our thinking (in whatever language we think in). The transcription to the machine is usually very smooth (there are very few syntax errors).
The problem comes when the documentation is incomplete, or doesn't describe the logic of the library perfectly. Our program might be subtly different from any scenario library author ever anticipated. But the building block we have in our head assumes the library is a flawlessly designed black box, a perfect abstraction. This doesn't even cause cognitive dissonance, because we don't even realize there's a flaw in our understanding (until later).
The way to eliminate logic bugs is to meticulously comb through the program in our heads, examining each building block in an orderly fashion for correctness, both in the code and in our minds. There are many techniques for doing this efficiently, which I'll leave as an exercise to the reader or a future post.
A byproduct of this process is that over time, our intimacy with libraries will grow wide and deep. We'll be able to spot bugs in others' code quickly because we realize where the program in their head has gone subtly awry. By looking at libraries that aren't our own, we learn how other programmers think — and we get better at thinking about programs.
Programming is a craft. By exploring the process of identifying bugs and improving the way we think about programs, we improve our craft.