5.8 Avoiding Errors and Debugging

  1. When naming methods, you should, as usual, choose descriptive identifiers. In addition, there are some naming conventions for methods that, if followed, should make your programs clearer and consequently less prone to errors. Since queries return values, it is common to name them with identifiers that indicate the value returned (total, sqrt, finalValue, and so on). Commands, on the other hand, do not return values; they perform some action. It is common to name them with identifiers that indicate the action that they perform (println, swap, rollDie, and so on).
  2. 
     
  3. It is sometimes difficult for beginning programmers to realize that parameter passing is done automatically by Java. Not only is there no need for the programmer to assign a value to a parameter on entry to a method, it is a mistake to do so since this will destroy the value that was passed to the parameter.
  4. 
    
  5. Remember that the value assigned to a parameter on entry to a method is a copy of the value of the corresponding argument. Thus, if you alter the value of a parameter, this will have no effect on the argument.
  6. 
    
  7. If a method returns a value, be sure that it does so for every possible situation. As an example, it is permissible to write
        if (a == b)
          return x; 
        else
    
          return y;
    
    but it would be an error if the method only returned a value when a and b were equal. If you fail to write a return statement for every possible case, the compiler will spot the error and refuse to compile the program.

Debugging

  1. To trace the actions of methods, use tracing statements at the beginning of each method and just before any return statements in the method. The tracing statements at the beginning of a method called foo should print "entering foo" along with the values of any parameters of the method. The tracing statements just before any return statements should print "exiting foo" along with the values of important local variables.
  2. 
    
  3. If a program containing methods is not executing correctly and the methods may be the source of problems, replace the actual methods temporarily. Queries can be set to return a constant and commands can be set to simply print messages. The temporary code can be turned on and off by a device similar to one suggested in the debugging section of Chapter 3. Create a boolean variable DEBUG that is set to true when debugging and false otherwise. Then replace the body of a method with something like the following.
        if (DEBUG)
          // action to be taken if debugging
    
        else
          // regular code of method

Exercise 5.8

  1. What is wrong with each method?
    (a) public static int largest (int a, int b)
        {
          // return the larger of the two parameter values
          if (a > b)
            return a;
          else if (b > a)
            return b;
          }
    (b) public static void applylnterest (double amount, double i)
        {
          // apply interest to amount at rate i%
          amount *= 1 + i/l00;
          return;
        }
    (c) public static double cubeRoot (double x)
        {
          // return the cube root of the parameter, x
          System.out.println("What is value?")
          x = In.getDouble();
          return math.pow(x,1.0/3.0);
        }
  2. Add statements to the method range that could be used to trace its actions.
        public static int range (int n)
        {
          int low, high;
          low = high In.getInt();
          for (int i 2; i <= n; i++)
          {
            int next = In.getInt();
            if (next>high)
              high = next;
            if (next < low)
              low = next;
          }
          return high - low;
        }