7.2. Hand and Eyeball Checks


Hand simulation

If you suspect that a method definition is wrong (which you should do if you have no good reason to believe that it is correct) then a good way to find an error is to step through the method body by hand on a simple parameter. When you see method calls in the body, assume that they work according to their contracts. If they don't, that is not this method's fault.

Do not try to perform a hand simulation in your head. Put your hand to work. Get a piece of paper and a pencil and show the variables. Do the simulation carefully on the paper. One of the most common mistakes is to do the simulation based on what you want the method to do rather than based on what the method body actually says. Pay attention to details.

You will find that quite a few errors can be diagnosed with hand simulations, and the simulation itself usually suggests a way to fix the error. You will fix errors much more quickly this way than by trying things without the benefit of understanding where the computation goes wrong.


Boundary values

Always test unusual parameters that are at some sort of boundaries or extremes. For example, if a method takes a nonnegative integer as a parameter, what does it do when that parameter is 0? Try things that are very small. If a method compares two values, what does it do when they are equal to one another?


Sanity checks

Sanity, or common-sense, checks are easy to carry out by inspection. They just make sure that a method definition is sensible, in common sense terms, without going through the details of a hand simulation. Here are some common sanity checks.

Do method calls have the correct number of arguments?

If you use a method that has 2 arguments, be sure that it is passed 2 arguments. If the method that you are defining is supposed to have 1 argument, according to its contract, make sure that it has 1 argument.

Inspect for type errors.

If a method expects an integer argument, check that you are passing it an integer. If a method returns an integer, make sure that you treat its result as an integer.

Check for returns.

If your method has a non-void return type, be sure that it returns a result no matter how the computation goes.

If your method returns a boolean result, it normally returns true sometimes and false sometimes. Check to see that both results are possible. If it only returns true, something is wrong.


Make sure that critical information is used.

A method usually needs to get some information from its arguments. Be sure that it mentions each argument. If an argument is a structure, be sure that it looks at each part of the structure that it needs in order to compute its result.

For example, suppose that method sum(L) is supposed to compute the sum of the numbers in a linked list of integers. Does it mention the item stored in a list cell? If not, then it does not look at the items at all, so it cannot possibly add them up.


Do not mix loops with recursion

In this course, we will never write a method that includes a loop and is also recursive. Check that you have not done that.

Check for repetition

If the problem that you are solving requires some kind of repetition because it needs more steps on larger arguments or inputs, then make sure that the repetition is done somewhere. The method will need to contain a loop, or it will need to be recursive, or it will need to call another method that performs repetition.

Check if vs. while

Beginners often write if where they mean while, or the other way around. Check that you have not done that.


Exercises

  1. Given the following method definition, perform a hand-simulation of f(3). Show the variables each time the loop reaches its beginning. What is returned?

      static int f(int x)
      {
        int i = 0;
        int s = 1;
        while(i < x)
        {
          i = i + 1;
          s = s + s;
        }
        return s;
      }
    
    Answer

  2. Given the following method definition, perform a hand-simulation of g( ). Show the array contents each time the second loop reaches its beginning. Also show the value that i will have for the next iteration. What does g( ) print? (Note: This method contains 3 loops, which we normally do not allow, but this is for illustration.)

      static void g()
      {
        int[] A = new int[5];
        for(int i = 0; i < 5; i++)
        {
          A[i] = i;
        }
        for(int i = 0; i < 4; i++)
        {
          A[i+1] = A[i] - 1;
        }
        for(int i = 0; i < 5; i++)
        {
          System.out.println(A[i]);
        }
      }
    
    Answer

  3. The following method has an error. Do an eyeball check to find the error.

      static int h(int x)
      {
        int y = x + 1;
      }
    
    Answer

  4. The following method has an error. Do an eyeball check to find the error.

      // w(x,y) returns the smallest prime number that
      // is greater than or equal to x and less than
      // or equal to y.  If there is no such prime
      // number, it returns 0.
    
      static int w(int x, int y)
      {
        int i = x;
        while(!isPrime(i))
        {
          i++;
        }
        return i;
      }
    
    Answer

  5. The following method has an error. Do an eyeball check to find the error.

      // z(x,y) returns the sum of x and y.
    
      static void z(int x, int y, int r)
      {
        r = x + y;
      }
    
    Answer