What we'd really like to be able to do is to write programs that do what we want them to do. This may sound simple, but it turns out that it isn't.
The problem of deciding whether a program is correct is a very difficult one. In fact, it's so difficult that a computer can't do it. (that is, there is no program which can tell you whether any arbitrary program is correct). However, you have to do it.
This may seem like a tall order, but don't forget that proving (all) theories in mathematics is also impossible for a computer, but mathematicians still go ahead a prove theories. Which suggests that perhaps people don't compute the same way that computers do? Or that we can still do significant, interesting, and worthwhile things even if we know beforehand that doing everything is impossible?
At any rate, writing a single program that can prove that any program that you write is correct is not possible, but it is possible for you to show that some programs are correct. In our case, we'll use a variety of techniques to try to make our programs as correct as possible.
First of all, knowing the language and practice are the best activities you can undertake in order to write correct code. Practice means making mistakes, and if making mistakes leads to learning about the mistakes, then the next time hopefully you avoid the mistakes and write more correct code. Trial and error. These are things that we've been trying to do in class, assignments, tutorials and so on.
Secondly, structure is crucial. You should try to write programs that consist of a bunch of small classes and short methods. Since the difficulty in verifying that a program is correct goes up very quickly as the program grows in size, we want to be able to look at small bits of the program (methods, loops, classes) and verify that they do their job properly. By verifying the small bits, we hope to be able to conclude that the program as a whole is correct, since it is made of the small bits. Verifying the small chunks of code is much easier than verifying large chunks of code.
Thirdly, style is important in coding. Using informative variable names, commenting the code properly, writing 'neatly' (that is, laying out the code in a standard way with indenting that helps you read it) are all useful in helping you to avoid and root out errors in your code. Style and structure are closely related -- there are many ways to write a program, and each way might give a program that does the same thing. Howver, some ways will be easier to debug, easier to modify if the requirements for the program change, and easier to pass on to someone else to work on. (i.e. more understandable). We'll talk about structure in the style section.
Fourthly, testing is crucial. Testing is the process of giving the program some input and verifying that the output is what we expect; it is also the process of giving a method input and verifying that it does what it is supposed to do. When you write code, you should always be mentally testing as you write the code. This means that you should be asking yourself 'what if the user does this' and 'what if the user does that' and 'what happens if the argument to this method is 0 -- does the method still do what I expect?'. You should strive to be both creative (in the sense that you're creating code) and critical (in the sense that you're analysing and critiquing your code) at the same time.
Finally, there are some tools that can help with debugging, such as an IDE, error-trapping methods, and other means to view the state of the program
In the following, we'll talk about style, testing, and tools.