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 usingparseDouble()
from theDouble
wrapper class. - The
parseDouble()
method will throw aNumberFormatException
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.
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 atry
block isolated the scope of assignment. This causes the compiler to believe that bothl
andw
may not have been initialized due to their assignment within the scope of thetry
block. The variablesl
andw
need to be initialized on line 6. - The
catch
blocks usesshowMessageDialog()
to display a message of failure, but the programmer is now relegated to terminating the program since continuing on is not an option.
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 inwhile
loops can help to promote a self-adjusting, self-healing solution. It also requires the addition of aboolean
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.
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 thereturn
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 ofl
andw
.
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);
}
}