How Many (Java) Classes Do You Need To Go (XP) Bowling?

An object-oriented developer searches for a reason to add more of them.

Ron Jeffries recently posted a couple of articles on simple design, with the
specific example of code to score a bowling game:

In a thread on the subject on the XP Mailing List, various posters expressed
a preference for one solution or the other.

With the caveat that I’m normally a very object-oriented guy, I prefer the
second (procedural) solution, in that I find has approriately simple design:
it work, expresses the programmer’s intentions, has (almost) no duplication
of ideas, and has the minimal amount of code needed to do all those things.

The point was made, though, that perhaps the procedural solution would fall
apart once the complexity of the problem increased. To test this idea, I decided
to extend it with the following features:

  • Know what frame the bowler is current done with / working one
  • Know the score of each frame
  • Know if the game is over
  • Reject erroneous input data

My first step was to convert the example C# code to Java. (I like C# at least
as much as Java, but for the moment I’m happier with the code-editing features
of Eclipse compared to VS.NET.) Here’s the Java code, the starting point before
adding any features:

/*
 * Trivial port of Ron Jeffries' Bowling to Java
 */
package bowling;

import java.util.ArrayList;

public class BowlingGame {

  ArrayList rolls = new ArrayList();

  public void roll(int roll) {
    rolls.add(new Integer(roll));
  }

  public int score() {
    int rollIndex = 0;
    int total = 0;
    for (int frame = 0; frame < 10; frame++) {
      if (strike(rollIndex)) {
        total += 10 + pinCount(rollIndex + 1) + pinCount(rollIndex + 2);
        rollIndex++;
      } else if (spare(rollIndex)) {
        total += 10 + pinCount(rollIndex + 2);
        rollIndex += 2;
      } else {
        total += pinCount(rollIndex) + pinCount(rollIndex + 1);
        rollIndex += 2;
      }
    }
    return total;
  }

  private boolean strike(int rollIndex) {
    return pinCount(rollIndex) == 10;
  }

  private boolean spare(int rollIndex) {
    return pinCount(rollIndex) + pinCount(rollIndex + 1) == 10;
  }

  private int pinCount(int pinPosition) {
    return ((Integer) rolls.get(pinPosition)).intValue();
  }
}

I also converted the NUnit tests to JUnit. (Formerly this was available for download,
but I’ve misplaced the file since then.)

With this in hand, I started adding tests for my new features. An example test:

  public void testStrikeWithFrameCounting() {
    game.roll(10);
    assertEquals(1, game.finishedFrames());
    assertEquals(0, game.scoredFrames());
    game.roll(5);
    assertEquals(1, game.finishedFrames());
    assertEquals(0, game.scoredFrames());
    game.roll(3);
    assertEquals(2, game.finishedFrames());
    assertEquals(2, game.scoredFrames());
    game.roll(2);
    assertEquals(2, game.finishedFrames());
    game.roll(1);
    assertEquals(3, game.finishedFrames());
    assertEquals(3, game.scoredFrames());
    rollMany(14, 0);
    assertEquals(10, game.finishedFrames());
    assertEquals(10, game.scoredFrames());
    assertEquals(29, game.score());
  }

This test, and others like it, verify that after each roll, the game object
know what frame has been completed, what frame is scorable, and when the game
is over. (I also added the feature to report the score of each frame, but didn’t
get around to testing it explicitly. I found that to get things right, I needed
a variety of tests for things happening in the last frame, since there are special
rules there.

Without further ado, here is working code to score the game, with the new features:

/*
 * Bowling Scorer, converted to Java, extended to know what
 * frame we are on, what frame has been scored, whether the
 * game is over, and the score of each frame
 */
package bowling;

public class BowlingGame {

  private static final int NUM_FRAMES = 10;
  private static final int NUM_PINS = 10;
  private static final int MAX_ROLLS_IN_GAME = NUM_FRAMES*2 + 1;

  // Input state:
  private int[] rolls = new int[MAX_ROLLS_IN_GAME];
  private int rollSoFar = 0;

  // Output state:
  private int[] frameScores = new int[10];
  private int scoredFrame;
  private int finishedFrame;

  // Processing variables; these would be locals, but
  // this class essentially is a "method object", so we
  // use instance variables instead of param passing
  private int scoringFrame;
  private int scoringRoll;

  public void roll(int roll) {
    if(roll<0 || roll>NUM_PINS)
      throw new RuntimeException("Roll out of range");

    if(gameOver())
      throw new RuntimeException("The game is over, no more rolls allowed.");

    rolls[rollSoFar++] = roll;
    calculate();
  }

  private void calculate() {
    scoredFrame = 0;
    finishedFrame = 0;
    scoringRoll = 0;
    for (scoringFrame = 1; scoringFrame <= NUM_FRAMES; scoringFrame++) {
      if (isStrike()) {
        scoreStrike();
      } else if (isSpare()) {
        scoreSpare();
      } else {
        scoreNormal();
      }
    }
  }

  private boolean isStrike() {
    return rolls[scoringRoll] == NUM_PINS;
  }

  private void scoreStrike() {
    storeFrameScore(NUM_PINS + rolls[scoringRoll + 1] + rolls[scoringRoll + 2]);
    frameIsScoredIfWeHaveRollOffset(2);

    if(scoringTheLastFrame())
      frameIsDoneIfWeHaveRollOffset(2);
    else
      frameIsDoneIfWeHaveRollOffset(0);
  }

  private boolean isSpare() {
    return rolls[scoringRoll] + rolls[scoringRoll + 1] == NUM_PINS;
  }

  private void scoreSpare() {
    storeFrameScore(NUM_PINS + rolls[scoringRoll + 2]);
    frameIsScoredIfWeHaveRollOffset(2);

    if(scoringTheLastFrame())
      frameIsDoneIfWeHaveRollOffset(2);
    else
      frameIsDoneIfWeHaveRollOffset(1);
  }

  private void scoreNormal() {
    storeFrameScore(rolls[scoringRoll] + rolls[scoringRoll + 1]);
    frameIsScoredIfWeHaveRollOffset(1);
    frameIsDoneIfWeHaveRollOffset(1);
  }

  private boolean scoringTheLastFrame() {
    return scoringFrame == NUM_FRAMES;
  }

  private void storeFrameScore(int frameScore) {
    frameScores[scoringFrame - 1] = frameScore;
  }

  private void frameIsDoneIfWeHaveRollOffset(int rollOffset) {
    if(scoringRoll + rollOffset < rollSoFar) {
      finishedFrame = scoringFrame;
    }
    // Continue scoring at the roll after the last one
    // on this frame:
    scoringRoll += rollOffset + 1;
  }

  private void frameIsScoredIfWeHaveRollOffset(int rollOffset) {
    if(scoringRoll + rollOffset < rollSoFar) {
      scoredFrame = scoringFrame;
    }
  }

  // The public interface has a few more methods for the new features:

  public int score() {
    int totalScore = 0;
    for(int i=0; i<frameScores.length; i++)
    totalScore += frameScores[i];
    return totalScore;
  }

  public int scoredFrames() {
    return scoredFrame;
  }

  public int finishedFrames() {
    return finishedFrame;
  }

  public int scoreForFrame(int frame) {
    return frameScores[frame-1];
  }

  public boolean gameOver() {
    return finishedFrame == NUM_FRAMES;
  }
}

Here is what I like about this solution:

  • There are tests to show that it actually works
  • The method names are, at least to me, intention-revealing
  • The methods are short and straightforward
  • The main scoring loop, which still happens in one straight-line pass, is
    simply this:

        for (scoringFrame = 1; scoringFrame <= NUM_FRAMES; scoringFrame++) {
          if (isStrike()) {
            scoreStrike();
          } else if (isSpare()) {
            scoreSpare();
          } else {
            scoreNormal();
          }
        }
  • There’s not much duplication left in there; perhaps someone can suggest
    a way to get rid of the bits that remain

The real question, of course, is whether this is too much for one class to
do – whether there are any parts of this code that should be a separate class.
The obvious candidates are the pairs of methods: should isStrike() and scoreStrike()
somehow be in a Strike class? They have an obvious parallel structure, a form
of duplication that I might be able to get rid of by adding classes.

I thought these new features would push me there – but they didn’t. Perhaps
a future story would do so. This implementation is still not quite “finished”,
in that I know there are more kinds of error conditions to consider, test for,
and implement. I don’t see any reason to think that adding those now would add
much to the conversation, so I didn’t add them.

One lesson of this exercrise, to me, is a common one: the problem space is
not the solution space
. Just because we have a thing called a Foo in the problem
domain, doesn’t mean we need a class Foo in the solution. We might, we might
not; with test-driven design, the need for a Foo should eventually become obvious.

Comments welcome, via email (address below) or on the XP mailing list.

Word Chains Kata Solution

I worked out a solution for “Pragmatic” Dave Thomas’s Code Kata 19 (Word Chains) in Java; it’s somewhat different than Dave’s published solution.

I’ve been watching PragDave’s Code Katas with interest, since I am also in the habit of occassionally solve a small, standalone programming problem just for the learning experience. Today I worked out a solution for Kata 19, Word Chains. I did this Kata the “pure” way, i.e. without looking at any of the discussion of solution approaches before coding. Here are the results (also on github). I wrote the code this time in Java.

Unlike Dave’s published solution, I didn’t precalculate adjacency lists; rather I took the more brute-force approach of scanning the word list at each step looking for neighbor words. In spite of that non-optimization, this still calculates the word chains for a bunch of examples in a few seconds (total).

I was curious how much of the program’s time is spent checking for neighbor words; this provided a good reason to try out a profiler plug for Eclipse, available on SourceForge. The profiler worked fine, and told me, as I would have guessed, that the program spends approximately 100% of it’s time looking at words to decide if they are neighbors (in the word-chains sense). Of course the usual optimization advice applies: it would have been actively stupid of me to optimize without measuring where the slow parts are.

PDA Application Walkthrough

Walkthough and screenshots of a PDA application development effort using the .NET Compact Framework, Embedded VC++, Embedded Visual Basic, Pocket Studio, and more.

This spring I created a site-inspection data collection PDA application for an Oasis Digital client. The first phase of that project was to build working prototypes of each part of such a system, in order to demonstrate what kind of application we will be able to create, and to bring my own skills up to date with current PDA development tools (my previous PDA work was a few years ago using the C/C++ Palm development tools). The prototype was a success, and led to a development effort for a system now deployed in production.

Along the way I learned a lot of things about the various tools for PDA applicationdevelopment, made a few dozen screenshots, and posted them here:

PDA Application Walkthrough

Now Forming: St. Louis Delphi User Group

In addition to Java and other high-profile tools and languages discussed on the site, Oasis Digital makes good use of Borland Delphi for Windows client applications. I’m interesting in forming a St. Louis Delphi User Group. (For those
of you around the world, this means the St. Louis, MO, USA metropolitan area.)

The first step is to attempt to find some developers and firms using Delphi in St. Louis. I don’t know if there are 2 or 2000 Delphi developers in the area, partly because many firms that use Delphi are rather quiet about it.

To facilitate communications, I set up a Yahoo Group… please join it:
http://groups.yahoo.com/group/delphistl/

Test Intensive Development in Delphi

Slides from a Birds of a Feather session at BorCon 2001

At the 2002 Borland Conference, I presented a “Birds of a Feather” session on Test Intensive Development in Delphi. A couple of dozen people attended, in spite of the early morning time slot. Most of the attendees were new to test intensive development, though a few were experienced in it and shared useful tips.

My introductory talk and demo was adversely impacted by a technical problem with the projector and missing microphone; hopefully this slightly expanded set of slides will fill in the gaps that caused.

Download TID-Delphi-BOF-Borcon-2002.ppt

A Content Management System

I generally say that reinventing the wheel is not a good idea. Sometime’s it’s an educational experience, though!

KCMS is Kyle’s Content Management System – a working name for the content
management system which “powers” this web site. It is an early work in progress, “version 0.1”
system. I put it together last fall to facilitate updating this site more easily.
It is composed of two parts:

On the web server, a few kilobytes of PHP code extracts content from a database,
applies a template, add in other elements (such as the advertisements), and thus
renders the page.

Unlike many other CMSs, the admin / authoring application is a
Windows application – not a web application.
It is shown here.


First, a login screen. This is logging in to an Interbase server on my machine;
I edit everything here, then push it to the production machine when it’s ready.
Although currently only I am editing content, this system would support multiple
users easily.


I use Internet Explorer as an ActiveX control for the "home". In
a business app, I would display some meaningful data there – some kind of current
snapshot of the problem space. For example, the number of orders placed so far
to day, month-to-date sales, etc. For the CMS I could indicate things like how
many articles need to be uploaded to the server.


The find / list screen is not all that helpful yet – it only filters on two fields (title and
full text), and sorts on one field at a time.


This is the above screen, filtered to articles that mention Delphi in the title.


Here are the details for one article / piece of content. This screen again
uses embedded IE to display a preview of the content. It uses the same style
sheet as the real web site, so the fonts and spacing match.


Right now, the only editing control is straight, un-high-lighted HTML. The
"edit content in DW" button launches DreamWeaver to edit this item
there. I may also provide an ability to launch GVIM or another HTML-aware editor
for syntax highlighting later.

Were this a commercial app, I could get a syntax highlighting component for Delphi
and provide good HTML and passable WYSIWYG. For an internal-use system,
using DreamWeaver works quite well.


The client software can connect to both the local development database and
the production database, and copy all updated data to the production system
on the web site. An alternative solution would be to apply templates and
generate static HTML locally, then FTP it to a non-database-equipped web
host. That would be quite useful for people who don’t want to pay for and support
database-capable web hosting solution.

That’s where I am so far. It’s all quite alpha – certainly many hours of work
would be needed to polish it up. It’s good enough to start using for content
though, so that’s what I did.


Motivation and Observations

Why did I do this, instead of just using FrontPage or DreamWeaver?

  • It’s my mechanism, I can add hooks as needed.
  • The template is stored just once, and applied as needed. This is a nice
    parallel to desirable software engineering practices, since it lets me tell
    the computer about the page layout "once-and-only-once".
  • The content is stored without any template applied. DreamWeaver applied
    each template "statically", so what I updated a template it would
    update every single page on the web site.
  • I can apply more than one template to the same content (i.e., printer-friendly
    version of each page). Because of the above points, I was able to add the
    "printer friendly" feature in less than an hour, and it works on
    every page powered by the CMS.
  • I can query the data, and automatically show the most recent additions on
    the home page, list everything on the listing page, etc.

What about other Content Management Systems?

Frontier / Manila looks quite nice, but I host all of this on a Linux machine.

I looked at a number of "open source" content management systems,
and it seemed like the effort to customize them to do what I wanted could easily
exceed the effort of building this from scratch.

Background on the URLs Used

When looking at some existing CMS systems, one of the things that bothered
me was the URLs they used. For example, I saw that BroadVision uses URLs like
this:

http://www.broadvision.com/OneToOne/SessionMgr/services/services_svp.jsp
?BV_SessionID=NNNN1165913018.1004016458NNNN&BV_EngineID=cccca
dcdgllkkdfcefecefedghhdfjl.0&serviceType=SolutionValueProposition&
channelname=Solution+Value+Proposition&channelRuleset=Services+Channels
&program
Name=Solution+Value+Proposition+Overview&programRule
set=Solution+Value+Proposition+Programs

Fortunately, I cannot afford Broadvision 🙂 . I suppose all of those characters in the URL
cost a lot of money.

With some excellent feedback from the St. Louis Web Developers’ user group
and elsewhere, I ended up with URLs like this:

http://sitename.com/story-NNN-other-text-here.html

The NNN is a number, and the other-text-here is a very short summary of the
page topic / title. These URLs have several advantages:

  • The look "static", so there is no risk of a human or search engine
    confusing them with per-user content (like a shopping cart, etc.)
  • They are short, and can be emailed without wrapping to multiple lines.
  • The CMS can key off of just the NNN part, so as I change page titles, old
    bookmarks will still work.
  • The URLs feel "harmless" to the end user who sees them.
  • There is some indication of the page content in the URL, which is quite
    helpful is a URL somehow becomes separated from its descriptions. I think
    this is superior to the approach used in Frontier Manila or in Vignette, both
    of which only have an identified.
  • It’s trivial to map these URLs to the proper content generation script using
    Apache’s mod_rewrite.

Why PHP?

PHP is ideal for small, simple needs like this. Although I use Java heavily
for enterprise web application development, the effort to install
and support a Java solution would not be justified for this app at this time.
The server part of this software consists of 2-3 PHP files and nearly zero installation
effort. I’ve implemented and personally deployed a number of Java web applications,
and it would still take me a good while longer to get such a solution running
here.

Why a Windows application for the authoring / admin?

Most content management systems use a Web interface for the administration
/ authoring interface. I found that I can build a good interface much more quickly
as a Windows application than as a web application – so why bother? I don’t
have any need at all for widespread, zero-deployment access to the admin interface.
I do have a need to work on the content when not even connected to the Internet.
Therefore, a Windows app was a good solution for my problem.