Skip to content

Programming by Design

If you're not prepared to be wrong, you'll never come up with anything original. – Sir Ken Robinson

  • About
  • Java-PbD
  • C-PbD
  • ASM-PbD
  • Algorithms
  • Other

Approaching a Project

Posted on April 30, 2012September 7, 2022 By William Jojo
Theory

When designing a basic application program, certain details may be elusive. For example, how many variables will be needed, or how many methods will need to be created. There is no simple prescription that can handle all of the possibilities. The only thing that can be done is begin to process the information and formulate a plan of attack.

When planning the strategy, other details will surface and stare glaringly back. More may simply be present waiting to be discovered. The next example details when the project needs more in order to be complete. In the program, the following will be addressed:

  • The set of variables.
  • The approach to gathering information.
  • Dealing with bad input.
  • Providing a method of escape.
  • Project morphing.

In Perimeter1, the program is simply calculating the perimeter of a quadrilateral using the length and width represented by l and w, respectively. The approach is simple, direct and uses a GUI to gather data and report results. The program is wrought with issues, however.

  • The programmer has chosen showInputDialog() for user input. This always returns a String.
  • The calculation can only be done with doubles, so each String will need to be converted using parseDouble() from the Double wrapper class.
  • The parseDouble() method will throw a NumberFormatException on values that are not in floating point format.
  • There are two places where an exception can occur. Lines 10 and 13 where parseDouble() is invoked.
Perimeter1.java
import javax.swing.JOptionPane;

public class Perimeter1 {

    public static void main(String[] args) {
        double l, w, p;
        String i, output;
        
        i = JOptionPane.showInputDialog("Enter the length");
        l = Double.parseDouble(i);
        
        i = JOptionPane.showInputDialog("Enter the width");
        w = Double.parseDouble(i);
        
        p = 2 * w + 2 * l;
        
        output = String.format("The length is %.2f%n", l)
                + String.format("The width is %.2f%n", w)
                + String.format("The perimiter is %.2f", p);
        
        JOptionPane.showMessageDialog(null, output);
        
        System.exit(0);
    }
}

The Perimeter2 program attempts to address the issue of exceptions. This introduces new problems that must be handled.

  • Wrapping the parseDouble() calls with a try block isolated the scope of assignment. This causes the compiler to believe that both l and w may not have been initialized due to their assignment within the scope of the try block. The variables l and w need to be initialized on line 6.
  • The catch blocks uses showMessageDialog() to display a message of failure, but the programmer is now relegated to terminating the program since continuing on is not an option.
Perimeter2.java
import javax.swing.JOptionPane;

public class Perimeter2 {

    public static void main(String[] args) {
        double l = 0.0, w = 0.0, p;
        String i, output;
        
        try {
            i = JOptionPane.showInputDialog("Enter the length");
            l = Double.parseDouble(i);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, "Naughty!");
            System.exit(1);
        }
        
        try {
            i = JOptionPane.showInputDialog("Enter the width");
            w = Double.parseDouble(i);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, "Naughty!");
            System.exit(1);
        }
        
        p = 2 * w + 2 * l;
        
        output = String.format("The length is %.2f%n", l)
                + String.format("The width is %.2f%n", w)
                + String.format("The perimiter is %.2f", p);
        
        JOptionPane.showMessageDialog(null, output);
        
        System.exit(0);
    }
}

Perimeter3 attempts to address the problems presented in Perimeter2 and does a relatively good job in doing so. Of course, new issues are introduced that must be handled.

  • Wrapping the try/catch blocks in while loops can help to promote a self-adjusting, self-healing solution. It also requires the addition of a boolean to know when the input has been successful.
  • The ok variable needs to be reset prior to starting the second loop for the width as this would now be true from the previous loop causing the program to bypass the second loop altogether.
  • Those paying close attention to this process are now considering the fact that code has repeated since we wrote Perimeter1 and has now escalated to the point where a method is a better fit to eliminate the repetition of code and reduction in the number of variables.
Perimeter3.java
import javax.swing.JOptionPane;

public class Perimeter3 {

    public static void main(String[] args) {
        double l = 0.0, w = 0.0, p;
        String i, output;
        boolean ok = false;
        
        while (!ok)
            try {
                i = JOptionPane.showInputDialog("Enter the length");
                l = Double.parseDouble(i);
                ok = true;
            } catch (Exception e) {
                JOptionPane.showMessageDialog(null, "Naughty! Try again.");
            }
        
        ok = false;
        while (!ok)
            try {
                i = JOptionPane.showInputDialog("Enter the width");
                w = Double.parseDouble(i);
                ok = true;
            } catch (Exception e) {
                JOptionPane.showMessageDialog(null, "Naughty! Try again");
            }
        
        p = 2 * w + 2 * l;
        
        output = String.format("The length is %.2f%n", l)
                + String.format("The width is %.2f%n", w)
                + String.format("The perimiter is %.2f", p);
        
        JOptionPane.showMessageDialog(null, output);
        
        System.exit(0);
    }
}

Perimeter4 is a complete solution that addresses all issues discovered throughout the process.

  • The getValue() method eliminates the need for a boolean and simply loops forever.
  • The parseDouble() call is the object of the return statement eliminating additional variables.
  • The user prompt is passed as an argument to getValue().
  • The main() method is smaller, simpler and no longer requires the initialization of l and w.
Perimeter4.java
import javax.swing.JOptionPane;

public class Perimeter4 {

    public static double getValue(String p) {
        String i;
        
        while (true)
            try {
                i = JOptionPane.showInputDialog(p);
                return Double.parseDouble(i);
            } catch (Exception e) {
                JOptionPane.showMessageDialog(null, "Naughty! Try again.");
            }
    }
    
    public static void main(String[] args) {
        String output;
        double l, w, p;

        l = getValue("Enter the length");
        w = getValue("Enter the width");
        
        p = 2 * w + 2 * l;
        
        output = String.format("The length is %.2f%n", l)
                + String.format("The width is %.2f%n", w)
                + String.format("The perimiter is %.2f", p);
        
        JOptionPane.showMessageDialog(null, output);
        
        System.exit(0);
    }
}

Post navigation

Next Post: Big-O Notation ❯

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Copyright © 2018 – 2025 Programming by Design.