Learn to use the debugger

Your favourite IDE has a powerful debugger which you can use to debug your programs. If you are new to programming, chances are that you are aware of it’s existence, but never use it.

The problem

Here is an example method, which has a problem. (It actually does nothing of value, but demonstrates the problem case). The method doSomething is called with a parameter, but the expected result is not returned.

public Box doSomething(Box foo, Box bar) {
  Box temp = foo.cloneMe();
  if (bar!=null) {
    Box newBox = new Box(bar);
    if (newBox!=null) {
      temp = doSomethingElse(foo);
      if (foo==null) {
        temp = bar;
      }
    }
  }
  return temp;
}

Here you can see the most frequent (ab)use of System.out.println statements.

public Box doSomething(Box foo, Box bar) {
  System.out.println("1");
  Box temp = foo.cloneMe();
  if (bar!=null) {
    System.out.println("2");
    Box newBox = new Box(bar);
    if (newBox!=null) {
      System.out.println("3");
      temp = doSomethingElse(foo);
      if (foo==null) {
        System.out.println("4");
        temp = bar;
      }
    }
  }
  return temp;
}

The developer’s intent is to trace which if-statements execute, so as to find the bug. If 1 2 3 is displayed in the console, the developer knows that foo==null evaluated to false.

An “enhancement” of this method is to add variables of interest in those System.out.println statements.

public Box doSomething(Box foo, Box bar) {
  System.out.println("1: " + foo + " " + bar);
  Box temp = foo.cloneMe();
  if (bar!=null) {
    System.out.println("2: " + temp);
    Box newBox = new Box(bar);
    if (newBox!=null) {
      System.out.println("3: " + newBox);
      temp = doSomethingElse(foo);
      if (foo==null) {
        System.out.println("4: " + temp);
        temp = bar;
      }
    }
  }
  return temp;
}

This is one of the most crude ways to debug a program. Unfortunately it’s quite common between junior developers. Note that if logging needs to be performed (for monitoring or historical purposes) a proper logging framework has to be used.

Things get interesting when the developer forgets to delete those System.out.println statements. The application is deployed, in a servlet container which hosts more applications, featuring code “debugged” in this way.
It’s not rare to see catalina.out logs which look like this:

INFO: Find registry server-registry.xml at classpath resource
20 Απρ 2007 10:23:24 μμ org.apache.catalina.startup.Catalina start
INFO: Server startup in 14063 ms
20 Απρ 2007 10:23:24 μμ org.apache.catalina.core.StandardContext reload
INFO: Reloading this Context has started
1
2
is null
3
copying file pic_01.jpg->temp/pic_01.jpg
copying file pic_02.jpg->temp/pic_02.jpg
copying file pic_03.jpg->temp/pic_03.jpg
copying file pic_06.jpg->temp/pic_06.jpg
1
2
is null
3
true
4
5
6

** BEGIN NESTED EXCEPTION ** 

java.net.ConnectException
MESSAGE: Connection refused: connect

STACKTRACE:

java.net.ConnectException: Connection refused: connect
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
...
is null
false
java.lang.NullPointerException
BoxExample$Box@126b249
1
2
is null
3
resultset was null
1
resultset was null
...

The solution

Learn to use your debugger. All you have to do is go to the line you want debugging to start, set a breakpoint (CTRL+F8 in Netbeans) and start the debug process. You will either debug the whole application (F5) or that single file/unit test (CTRL+SHIFT+F5).
You can set watches, see the stacktrace and examine the contents of all the local variables at any time in the program execution. You get orders of magnitude more power, in less time; for free!

Try it out. When you get used to it, you’ll never look back.

Comments are closed.