Lab 3

Style and Maintainability

There are two important concepts to learn about software engineering:

  1. Writing code that solves useful problems, and
  2. Writing code that can be easily maintained.

Too many people focus on #1 at the expense of #2.

Why writing maintainable code is important

There are several reasons why code has to be maintained. The first is bug-fixes. Assume that you write a useful program that lots of people like. The users will eventually find small errors that effect the program's value. If you want people to keep using it, then they need to be fixed.

The second is allowing for growth. Your users will frequently request additional features to make your program easier to use or more useful. Think of the growth in MIDS - the database has a lot of uses, and new features are added every year.

The third is to respond to changes in the environment. Operating Systems get updated constantly, and some of the changes may eventually not be reverse-compatible with your program. Your program will have to be updated and recompiled to keep it working. This happens frequently with Java. The JVM (Java Virtual Machine) changes several times a year. Every time the JVM changes, your program needs to be tested against the new version and any new problems fixed.

We generally spend more money maintaining a program than writing it in the first place. A team of 5 programmers may build a new application in a year, and then a single programmer may maintain it for the next 10 years. That is a 2:1 ratio of maintenance to development costs over the life of the program. We can keep those costs down by writing code that is easily maintainable.

What does maintainable code look like?

That is a tough question. At a minimum, it should:

That last item (checking for invalid data entries) is important. We are going to implement input-checking in today's lab.

What does non-maintainable code look like?

This is an easier question to answer, if only because there are so many good examples.

Here a programmer describes some code a co-worker had written that will be expensive to maintain and can be expected to break frequently (source: http://googlesystem.blogspot.com/2006/07/collection-of-funny-source-code.html):

   Once I had a junior programmer writing VB code that needed to know the day of the week. 
   He decided to write his own code, and read something like:

   if (day = 1) or (day = 8) or (day = 15) or (day = 22) or (day = 29) then
   weekday = "Monday"
   elseif (day = 2) or (day = 9) or (day = 16) or (day = 23) or (day = 30) then
   weekday = "Tuesday"
   ...

   Trying to be educational I asked him for his opinion about his own code, 
   and he said that he would simply modify it every month.

There are annual contests to develop "Obfuscated Code". These are computer programs that are nearly impossible to read. The winners of one such contest are here: IOCCC. Take a look at the *.c files on this page for some good negative examples.

Non-maintainable code is easy to spot when you see it, but has many different causes. Here are some clues to help you spot it in the wild:

Code style

You will see lots of attempts at defining a code-style for your organization. There is no one best style for formatting neat code, but it is important that all members of an organization use the same style as each other. For this purposes of this lab, your code must meet the following style:

Class Names have a first letter that is upper-case. If the name is a compound word, then each subsequent word is capitalized as well. The rest of the word is lower-case.

Variable Names have a first letter that is lower-case. If the name is a compound word, then each subsequent word is capitalized. The rest of the word is lower-case.

Function Names follow the same rules as variable names.

Constant Names are always all caps.

Whitespace Every time you nest a new set of brackets {}, the code beneath must be indented exactly 4 spaces. Tabs may not be used for indenting, since different editors will indent tabs different amounts. Below is a good example.

    public static class Mid {
        public int alpha;
        public String firstName;

        public Mid(int a) {
            alpha = a;
        }
    }

Brackets Brackets {} indicate function and class boundaries. The open bracket { should be placed on the same line as the function or class name, with one space before it. The closing bracket } should line up under the start of the class/function name. Similar styles should be used for if(), etc. The else {} statement must be lined up under the if {}, and not not be on the same line as the if's closing bracket. See below:

    public static class Mid {       //GOOD
        public Mid(int a){          // BAD
            alpha = a;
        }                           // GOOD
        public Mid(int a)
        {                           // BAD
            alpha = a;
    }                               // BAD 
        public Mid(int a){alpha=a;} // VERY BAD
        
        public void test() {        // GOOD
            if(alpha) {             // GOOD
                ...
            } else {                // BAD
                ...            
            }                       // GOOD
            else {                  // GOOD
            
            }
    }                               // GOOD

Lab Assignment

In this lab, we are going to implement a fairly simple program that uses the tools you have learned so far in class. The key element that we want you to think about maintainability. Your code must meet all of the design requirements given below as well as the style guide given above.

Your code is going to read four float values from the command line. These values are the X and Y coordinates of two points. Your program is going to calculate the length of the line segment that connects those points.

Our classes

Point.java will hold the values of the vertices.

Line.java will hold the two Points and will calculate the length between them.

Lab03.java will read in the floats from the command line, verify that they are proper input values, pass them the Line's constructor, and ask the Line for its length. It will output an error and quit if it detects invalid command-line input.

The assignment

Here are the program Requirements:

  ~/ic211/Lab03$ java Lab03 1 1 -1 -1  
  Line length: 2.8284
  
  ~/ic211/Lab03$ java Lab03 1 1 -1 -1 0 
  ERROR: Too many command-line variables. Four required.

  ~/ic211/Lab03$ java Lab03 1 1 -1 
  ERROR: Too few command-line variables. Four required.

  ~/ic211/Lab03$ java Lab03 1 1 -1 2 
  ERROR: Values must be in range -1 <= n <= 1.

Extra Credit

Here is one extra credit item. Your program should additionally check whether the four items passed on the command-line are numbers at all. Doing so requires using Exceptions, which we have not covered yet. Basically, an Exception is Java's way of saying that it encountered an unexpected error and does not know how to proceed. An example of an Exception is trying to covert the word "Potato" into a float. This type of error happens frequently when we parse user-input.

Exceptions use a try/catch statment that is similar to an if/else statement. The catch{} block runs only if the try{} block encounters an error.

This program iterates over the command-line and checks whether the input strings can be converted to floats:

 
    public class ExceptTest {
        public static void main(String[] args) {
            for (int i = 0; i < args.length; i++) {
                try {
                    Float f = Float.parseFloat(args[i]);
                    System.out.println("FLOAT: " + f);
                }
                catch (NumberFormatException nfe) {
                    System.out.printf("ERROR: cannot convert '%s' to a float.\n", args[i]);
                }
            }

        }
    }

    ~/ic211/Lab03$ java ExceptTest 1 1.2 1.2.3 Potato 4
    FLOAT: 1.0
    FLOAT: 1.2
    ERROR: cannot convert '1.2.3' to a float.
    ERROR: cannot convert 'Potato' to a float.
    FLOAT: 4.0

If you run the above input without using a try{} block, you will get the following error:

Exception in thread "main" java.lang.NumberFormatException:

What to hand in

You need to hand in the three files that you created: