Michael Bolin's 6.170 Recitation

This web site is for members of the recitation that I am teaching for 6.170 Spring 2004. The recitation meets Thursday mornings from 10-11am in 26-210. Here you will find recitation notes as well as links to software development tools that I consider important.
Recitation Notes
2/5 Recitation 1
2/12 Recitation 2
2/19 Recitation 3
2/26 Recitation 4
3/4 Recitation 5
Comments on Problem Sets
Problem Set 0
Problem Set 1
Problem Set 3
Things I Recommend
Software You Should Install
Books You Should Own
Web Sites You Should Use

Comments on Problem Set 0

RandomHello Revisited

We saw a "Hall of Fame" example of RandomHello in lecture this week, but I wanted to juxtapose it with a "Hall of Shame" example to reveal and reinforce good code versus bad code.

"Hall of Shame" RandomHello1.java Example: "Hall of Fame" RandomHello2.java Example:


public class RandomHello1 {

  public void sayHello() {
    // array of greetings
    String greetings = new String[5]; 
    // first greeting
    greetings[0] = "Hello World";
    // second greeting
    greetings[1] = "Hola Mundo";
    // third greeting 
    greetings[2] = "Bonjour Monde";
    // fourth greeting
    greetings[3] = "Hallo Welt";
    // fifth greeting
    greetings[4] = "Ciao Mondo";
    // random number generator
    Random random = new java.util.Random();
    // print random greeting
    System.out.println(random.nextInt(4));
  }

}
import java.util.Random;

public class RandomHello2 {

  private String[] greetings = {
    "Hello World",
    "Hola Mundo",
    "Bonjour Monde",
    "Hallo Welt",
    "Ciao Mondo"
  };

  private Random random = new Random();

  public void sayHello() {
    int index = random.nextInt(greetings.length);
    System.out.println(greetings[index]);
  }

}

Differences between RandomHello1 and RandomHello2:

  1. RandomHello2 uses an clear import statement at the top of the file instead of hiding the import in the code. This makes it easier to locate the dependencies of RandomHello. You will appreciate the benefits of this later when you have to start drawing Module Dependency Diagrams. (Eclipse Tip: remember that you can organize your imports in Eclipse by using Ctrl-Shift-O)
  2. RandomHello1 is littered with uninformative comments. For an explanation of what is an informative comment, see Supplementary Handout 1: Java Style Guide. For some additional info about comments, you should also see last week's recitation notes.
  3. The 4 in nextInt(4) is incorrect! Because the developer misread (or failed to read) the specification for nextInt(), he plugged in the wrong literal value – it should be 5. Although...
  4. RandomHello1 has magic numbers. A magic number is a number besides -1, 0, or 1 that is embedded in your code. Such constants should be abstracted out of your methods as static final fields at the top of your class as follows:
        public static final int MAX_GREETING = 4;
    
    Note that the name of this variable is capitalized because it is static which is the convention for static variables in Java. Capitalization makes these variables stand out in your code. If magic numbers are not abstracted out, then developers will start pasting the literal number all over place. Then what then number needs to be changed (in this case, when a greeting is added), you have to do a search-and-replace for the literal value. When this number is a static final int, it only needs to be changed in one place.

    The numbers -1, 0, and 1 are exempt from this rule because they are often used in simple comparisons where such abstraction would just be overkill:

      // an example of too much abstraction!
      public static final int NEGATIVE_ONE = -1;
    
      public boolean containsCharacter(String s, char c) {
        int index = s.indexOf(c);
        return (index > NEGATIVE_ONE);
      }
    
    As you can see, this is a little silly, so don't worry about abstracting out numbers such as this. Although, whenever possible, generate numbers that depend on other values instead of declaring them as constants:
  5. RandomHello2 uses greetings.length so that the number passed to nextInt will always be correct, even if the length of greetings changes. These issues culminate to the following major difference between RandomHello1 and RandomHello2:
  6. If a greeting is added to RandomHello1, the code needs to be changed in three places, but if a greeting is added to RandomHello2, the code only needs to be changed once. In your code, you should try to localize information as much as possible. RandomHello1 spreads this information out unnecessarily, making the code more difficult to maintain.
  7. RandomHello2 creates the variables random and greetings once whereas RandomHello1 creates these two variables every time sayHello() is called. Thus, RandomHello1 unneccessarily uses more memory than RandomHello2. (Arguably, the behavior varies between RandomHello1 and RandomHello2 because of the differences between using a new Random every time or a seeded Random multiple times, but this is probably inconsequential in this case.)
RandomHello1 may be obfuscated with all of the comments, but even if you removed all of them, there is still a distinct simplicity in RandomHello2 over RandomHello1. Strive for simplicity in your code. As Albert Einstein said, "Make everything as simple as possible, but not simpler."


©2004 Michael Bolin