home account info subscribe login search My ITKnowledge FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
To access the contents, click the chapter and section titles.

Sams Teach Yourself Visual J++ 6 in 21 Days
(Publisher: Macmillan Computer Publishing)
Author(s): Rick Leinecker
ISBN: 0672313510
Publication Date: 11/01/98

Bookmark It

Search this book:
 
Previous Table of Contents Next


Good Design Can Prevent the Need for Debugging

You now know how to use the Visual J++ debugger. These skills will help you get the most out of the debugger. But there’s more to debugging than knowing which key to press and which window to watch. You need to develop a systematic approach to debugging programs. A random or haphazard technique will waste time and produce intermittent results.

Design Your Program Carefully

It might sound strange to talk about program design in a chapter about debugging. But if you think about it, it’s not strange at all. A properly designed program will prevent more bugs than you’ll ever know and will make the debugging process easier when the need arises.

If you’re a software developer in a company that has several developers, somewhere along the way someone will reuse some of your code or inherit your project. That person will have no chance of understanding your program, especially when it comes to debugging, if it’s not properly designed.

Organize Your Program Well

Principle number one: organize your program into easily understood chunks. I once took over a project from a developer who was long gone from the company. He used a method named redrawScreen(). This is easy enough to understand. My guess at first glance was that this method redraws all information on the screen. I couldn’t have been more wrong. Although the first couple of lines redrew the screen, the rest of the huge method did stuff such as checking a user’s database connection, calculating variables that had nothing to do with the screen redraw, and checking the state of some hardware peripherals.

This method should have never included anything except the screen redraw code because it was called redrawScreen(). The extra couple of minutes it would have taken the programmer to create separate methods for the unrelated code would have been well worth it. Not only would he have had an easier time debugging the program, but I would have had an easier time understanding it as well.

I’m not just whining to have an easier time. When a program is easier to debug, it saves time. And this translates into a monetary value for the employers of software developers. Anything a developer can do to save time in the long run is good. I know what the pressure of a deadline is like. But don’t use sloppy techniques, even if something is due tomorrow.

Let’s take a look at a simple example. Consider the following code:

int m_nVolts, m_nAmps = 2, m_nOhms = 200;
int m_nSpeed, m_nDistance = 120, m_nTime = 2;
double m_dKinetic, m_dMass = 5.0, m_dVelocity = 3.0;

public void mainProgram()
{

    // Do stuff here.

    calculateStuff();

    // Do stuff here.

}

public void calculateStuff()
{

    // Calculate volts.
    m_nVolts = m_nOhms * m_nAmps;

    // Calculate speed.
    m_nSpeed = m_nDistance / m_nTime;

    // Calculate kinetic energy.
    m_dKinetic =
        ( m_dMass * m_dVelocity * m_dVelocity ) / 2;

}

The main program code calls a single method, which then makes three different calculations. This is a simple example, so it might appear okay on the surface. But consider how it would look if the three calculations were complicated, maybe a hundred lines of code each. And what if this program wasn’t the trivial example that it is, but instead a program of ten thousand lines of code?

Your program all of a sudden develops a problem. It’s incorrectly calculating kinetic energy. To debug this, you have to step into the calculateStuff() method. Now, instead of strictly debugging the kinetic energy calculations, you’re mixed up with two other calculations.

The situation gets even more mixed up when you declare local variables, maybe just some temporary counter and scratch variables, and use them for all three calculations. There’s a principle of object-oriented programming called encapsulation. It’s one of the cornerstones of object-oriented programming. In a strict sense, encapsulation means separating the implementation details from the abstraction. This is what we want to do—separate the three calculations so that they are by themselves. This technique makes them easier to understand and far easier to debug.

The following change to the preceding poorly designed example follows:

int m_nVolts, m_nAmps = 2, m_nOhms = 200;
int m_nSpeed, m_nDistance = 120, m_nTime = 2;
double m_dKinetic, m_dMass = 5.0, m_dVelocity = 3.0;

public void mainProgram()
{

    // Do stuff here.

    calculateVolts();
    calculateSpeed();
    calculateKinetic();

    // Do stuff here.

}

public void calculateVolts()
{

    // Calculate volts.
    m_nVolts = m_nOhms * m_nAmps;

}

public void calculateSpeed()
{

    // Calculate speed.
    m_nSpeed = m_nDistance / m_nTime;

}

public void calculateKinetic()
{

    // Calculate kinetic energy.
    m_dKinetic =
        ( m_dMass * m_dVelocity * m_dVelocity ) / 2;

}


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.