CSCI 241 Labs: PreLab 2
Basic Programming and Debugging Techniques


Introduction

So far in the textbook, we have seen programs written correctly and ready to run. There is no hint of the process involved to get them into their final form. However, there are a lot of ways to make mistakes when even writing a "simple" program. Any programmer who claims to never make mistakes is lying!

Programming is known to be frustrating. Error messages can be confusing and intimidating. Experienced programmers expect this and learn to work through them, one by one.

A language like Java is very complex. As one learns a new language, errors seem to occur way too often. Keep in mind that a good programmer is also part detective, observing clues wherever they may be found in order to correct the errors which inevitably occur.

Types of Errors

Errors can appear in your programs in any part of the design or implementation process. We want to find errors as early in the process as possible. We will begin by concentrating on the most common types of coding errors which occur when first learning a programming language: syntax errors and logic errors.

A syntax error is one that the compiler detects. A Java compiler can't figure out what you intend to do in your program, it only recognizes that it cannot translate what you wrote into byte code. This is why a syntax error is also called a "compile-time" error. Some examples of syntax errors include:

BlueJ displays, at most, one error message at a time, highlighting the line of code where it detected the problem. Sometimes the error is on that line and sometimes it is caused by an error in a previous line of code. Other IDEs may show multiple error messages after a program is compiled. Sometimes fixing one problem fixes others, and sometimes fixing the original problem illuminates additional problems in later code. It is up to you, as the programmer, to decide the type of correction(s) needed.

A logic error occurs when your program runs but does not give you the result you expect. This is why it's important to create test data, along with predicted results, when you design a program. Some examples of logic errors include:

Aside:
A third type of error which does not occur quite as often is a runtime error. These types of errors usually come from erroneous input values, such as entering a letter when the program expects to read a number. Programmers can spend many lines of code making sure input values are appropriate. If the input is invalid, the program will return to the data entry page and ask for the information again so that bad data doesn't make it any further along in the process. We do not yet have the tools to build this kind of coding into our programs, but you will have a chance to do so in a future chapter.

Isolating and Fixing Errors

Java is notorious for having many decidedly unhelpful error messages. In today's lab, you will see some of Java's error messages and begin to associate them with common mistakes.

If you understand the error message right away, you can easily type the correction in the indicated line.

To fix more mysterious errors, there are three main debugging techniques (which work in any language and IDE):

  1. When learning a new language, compare what you wrote to similar lines in a working example such as found in the textbook. A little mistyping can cause a big problem!

  2. Use a System.out.println() statement to print the value of any variable, at any step along the way. Sometimes we can see that a variable starts out with the correct value but gets an incorrect value inside the program. Adding print statements within the code lets us see the current value. For example, this line prints the value of a variable named total:
    System.out.println("total = " + total);
    If total was holding the value 25, you would see this line printed:
    total = 25
    When printing the value that a variable holds, try to get in the habit of printing the name of the variable before the value. It really helps when you need to print the values of more than one variable.
  3. Temporarily comment out the indicated line in order to see if the earlier lines are okay. We do this by inserting two forward slashes (//) at the beginning of the line. Once we know the other lines are working, we can copy this line and edit the copy by removing the forward slashes and making the correction. If we compile and run the program and find it still isn't right, we can see both the original and how we changed it at the same time.

Later this semester:
A fourth technique is to use an IDE's built-in debugger program. Most IDEs have them these days, including BlueJ. Feel free to explore BlueJ's debugger on your own if you wish, but try to do without it for this week's lab exercises.

Future Coursework Preview:
Software Engineering (studied in a 2-course sequence here at UW-Parkside) is defined as the process of designing and implementing large programs and systems. In today's world, some well-known programs (such as Google or Microsoft Office) can involve hundreds and thousands of programmers. Managing this complexity is very different than managing your own work. However, since large programs consist of many small parts working together, we can use a software engineering technique called the Personal Software Process to help understand and improve our code.

Watts Humphrey, whom some call the "father of software quality", defined the process as follows:

The personal software process (PSP) is a self-improvement process designed to help you control, manage, and improve the way you work. It is a structured framework of forms, guidelines, and procedures for developing software. Properly used, the PSP provides the historical data you need to better make and meet commitments and it makes the routine elements of your job more predictable and more efficient.

This process tells us to keep track of what happens during the development of software, writing down what happens along the way in order to make things work more smoothly when tackling a similar project. As you might imagine, this process can be very tedious and for a simple program, can even take longer than the programming itself. We won't require you to do this type of detailed analysis in lab this week. But, keep the reasoning in mind while you work with the programs, recording and deciphering error messages in the hopes of figuring things out more quickly next time.