teaching machines

CS 1: Lecture 32 – Stopwatch

Dear students,

As with methods, a primary benefit of object-oriented programming is code reuse. We can create a utility and use it over and over again, in many contexts. We will do just that by designing a Stopwatch class. We will use it to time a few operations:

  1. a words-per-minute calculator
  2. the amount of time it takes to brute force crack a password
  3. a competition to type in the alphabet backward

But first, let’s split into pairs and discuss what this Stopwatch should look like. With your neighbor, write down answers to the following questions:

  • What behaviors should a Stopwatch class support? Write down method signatures (name, return type, parameters).
  • What state must we track in order for the Stopwatch to do its job? Write down variable declarations (types and names).

When we model an object, we are tempted to give it every feature imaginable. We humans are enumerators. Completionists. However, this sort of behavior is the undoing of many a project. It’s better to ship a product that does one task well then ten tasks poorly. (Even better is to do ten tasks well. But that’s usually not one of our options.) Modern software development follows the principle of YAGNI—”you ain’t gonna need it.” The spirit of this aphorism is to reign in your dreams to just the required functionality, at least initially. Don’t write code unless it’s meeting a felt need.

Here’s your TODO list for next time:

  • I think there’s enough going on.

See you next class!

Sincerely,

P.S. It’s time for a haiku!

The bigger your lawn
The less time to enjoy it
Just say no mo-er

P.P.S. Here’s the code we wrote together…

Midterm.java

package lecture1129;

public class Midterm {
  public static void main(String[] args) {
    System.out.println(abc123("Gods kalpot Latvijai!!1!"));
  }
  
  public static String abc123(String s) {
    String sPrime = "";
    for (int i = 0; i < s.length(); ++i) {
      if (Character.isLetter(s.charAt(i)) ||
          Character.isDigit(s.charAt(i))) {
        sPrime += s.charAt(i);
      }
    }
    return sPrime;
  }
}

Stopwatch.java

package lecture1129;

public class Stopwatch {
  private long startMillis;

  public Stopwatch() {
    startMillis = -1;
  }
  
  public void start() {
    startMillis = System.currentTimeMillis();
  }
  
  public double stop() {
    if (startMillis == -1) {
      throw new IllegalStateException("Can't stop unstarted stopwatches, punk!");
    }
    
    long stopMillis = System.currentTimeMillis();
    return (stopMillis - startMillis) / 1000.0;
  }
}

Password.java

package lecture1129;

public class Password {
  public static final String SECRET2 = "of";
  public static final String SECRET3 = "tri";
  public static final String SECRET4 = "slar";
  public static final String SECRET5 = "three";
  public static final String SECRET6 = "foobag";
  public static final String SECRET8 = "splatbot";
}

BruteForce.java

package lecture1129;

public class BruteForce {
  public static void main(String[] args) {
    Stopwatch excalibur = new Stopwatch();
    excalibur.start();

    // long running operation
    for (char a = 'a'; a <= 'z'; ++a) {
      for (char b = 'a'; b <= 'z'; ++b) {
        for (char c = 'a'; c <= 'z'; ++c) {
          for (char d = 'a'; d <= 'z'; ++d) {
            for (char e = 'a'; e <= 'z'; ++e) {
              for (char f = 'a'; f <= 'z'; ++f) {
                for (char g = 'a'; g <= 'z'; ++g) {
                  for (char h = 'a'; h <= 'z'; ++h) {

                    String possiblePassword = "" + a + b + c + d + e + f + g + h;
                    if (Password.SECRET8.equals(possiblePassword)) {
                      System.out.println(possiblePassword);
                    }
                  }
                }
              }
            }
          }
        }
      }
    }

    System.out.println(excalibur.stop());
  }
}

Stopwatch.java

package lecture1129;

public class Stopwatch {
  private double elapsedSeconds;
  private double startSeconds;
//  private double endSeconds;
  private boolean isRunning;
      
  public Stopwatch() {
    isRunning = false;
  }
  
  public void start() {
    isRunning = true;
    startSeconds = System.currentTimeMillis() / 1000.0;
  }
  
  public void stop() {
    if (!isRunning) {
      throw new IllegalStateException("You can't stop an unstarted stopwatch, \u324A!");
    }
    
    isRunning = false;
    double endSeconds = System.currentTimeMillis() / 1000.0;
    elapsedSeconds = endSeconds - startSeconds;
  }
  
  public double getElapsedSeconds() {
    return elapsedSeconds;
  }
  
//  public void reset() {
//  }
}

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *