CIT 591 Number Personalities
Fall 2006, David Matuszek

The assignment:

In the Number Personalities assignment I asked you to determine, for the numbers 1 through 100 (and a few additional numbers), whether each number was prime, happy, triangular, square, smug, and honest. Here, I provide four variations of my code, with comments.

Version 1 -- OK

There's nothing really wrong with this version, but it has six blocks of the form

 if (prime(number)) {
     System.out.print("prime, ");
 }
 else {
     System.out.print("composite, ");
 }

These make the main method less readable and a lot longer than it needs to be.

Version 2 -- worse

In this version, we simplify the main method by moving the print statements into the various methods. This makes the main method more readable--the heart of the main method now looks like

 prime(number);
 happy(number);
 triangular(number);
 square(number);
 smug(number);
 honest(number);

This looks nice, but the problem is that now all the methods are "noisy"--they do output--and each does more than one simple thing--it computes, plus it prints. This makes the methods unsuitable for use in any other program, where we might not want that printing to happen. Plus, it gets in the way of JUnit testing. On top of all that, it introduces a bug--do you see it?

Version 3 -- bettter

Version 3 introduces one simple method to do most of the printing:

private static void tellIf(boolean test, String yes, String no) {
    if (test) System.out.print(yes);
    else System.out.print(no);
}

and the calls in the main method are slightly longer, but at least they can be named so as to tell you what is happening:

tellIf(prime(number), "prime, ", "composite, ");
tellIf(happy(number), "happy, ", "unhappy, ");
tellIf(triangular(number), "triangular, ", "not triangular, ");
tellIf(square(number), "square, ", "not square, ");
tellIf(smug(number), "smug, ", "not smug, ");
tellIf(honest(number), "honest", "dishonest");

Version 4 -- better yet

In each of these cases, the loop in the main method is fairly long:

while (number < 100) {
    number = number + 1;
    System.out.print(number + "    ");

    tellIf(prime(number), "prime, ", "composite, ");
    tellIf(happy(number), "happy, ", "unhappy, ");
    tellIf(triangular(number), "triangular, ", "not triangular, ");
    tellIf(square(number), "square, ", "not square, ");
    tellIf(smug(number), "smug, ", "not smug, ");
    tellIf(honest(number), "honest", "dishonest");
    
    System.out.println();
}

and none of these programs meets an additional requirement--that, after doing the first 100 numbers, you try the code with a handful of larger numbers. This would require repeating the six calls to tellIf for every number we want to test. So in version 4, I introduce yet another method,

private static void tellAboutNumber(int number) {
     System.out.print(number + "    ");
     tellIf(prime(number), "prime, ", "composite, ");
     tellIf(happy(number), "happy, ", "unhappy, ");
     tellIf(triangular(number), "triangular, ", "not triangular, ");
     tellIf(square(number), "square, ", "not square, ");
     tellIf(smug(number), "smug, ", "not smug, ");
     tellIf(honest(number), "honest", "dishonest");
     System.out.println();
}

and in the main method I have

while (number < 100) {
    number = number + 1;
    tellAboutNumber(number);
}
System.out.println();
tellAboutNumber(12345);
tellAboutNumber(1024);
tellAboutNumber(1028);
tellAboutNumber(320);

Moral:

Use well-named methods to make your code shorter and more readable.