The Beginning of Extreme Programming

Kent Beck's Smalltalk implementation of '99 Bottles of Beer On The Wall' was the spark that launched Extreme Programming.

As a member of the Chrysler C3 team, I was challenged to learn how to build systems using Object Oriented techniques. One of the tools I and others on the team used was the comp.lang.smalltalk discussion group. Late in 1995, someone posted a message to most of the comp.lang groups asking the a program be posted in the group's language showing how the lyrics to the song '99 Bottles of Beer on the Wall' should be generated. There were several postings in the Smalltalk group, most of which were not too inspiring. I then saw the code listed below. A little while later, we decided we needed help performance tuning our application, and I suggested we talk to this Beck guy.

It turns out that our code was too much like that that did not impress me and with Kent's (,and Ron Jeffries's, Martin Fowler's, Jim Huangs's, and Ken Auer's) we built a system that looked much more like this one.

Subject: Re: 99 bottles of beer, auf Smalltalk

Date: 1996/01/26 Author: Kent Beck

There has been a discussion recently on comp.lang.smalltalk about how best to represent the song "99 Bottles of Beer on the Wall" in Smalltalk. Apparently, there has been some use of this song as a way of benchmarking various programming languages.

I found the Smalltalk implementations appalling in their lack of use of the facilities that make Smalltalk so powerful. In particular, the previously published solutions all made heavy use of iteration and conditional logic.

In my quest for intellectual purity, the limits of absurdity, and a decent distraction from this nasty cold, I have undertaken to write the one true definitive Smalltalk version. I hereby place the following code, written in literate program form, into the public domain, to stand as a monument for the ages, or until my hard disk crashes again, whichever comes first.


We need a program which takes as input, N, a number of bottles of beer and produces as output a string containing the N+l verses of the bottles of beer song. For N=3, the expected output is:

'3 bottles of beer on the wall 3 bottles of beer Take one down and pass it around 2 bottles of beer on the wall

2 bottles of beer on the wall 2 bottles of beer Take one down and pass it around 1 bottle of beer on the wall

1 bottle of beer on the wall 1 bottle of beer Take it down and pass it around No bottles of beer on the wall

No bottles of beer on the wall No bottles of beer There are no more to pass around No bottles of beer on the wall '

Note the subtle changes, verse to verse, that will necessitate the application of powerful object-oriented techniques. The third line changes, as does the plurality of the number of bottles.


The fundamental question in any object oriented development is "what is my first object?" Until this question is answered aright, nothing else the developer does will be of much use. Fortunately, we have in "song" a natural unit of computation, the Verse. Introducing varying kinds of Verses will allow us to capture with polymorphic messages logic that must be expressed as explicit conditionals in procedural languages. Such future flexibility is of uncertain use with a problem like BOB (Bottles of Beer song), but that's the thing about future requirements, you don't know what they're going to be.

   subclass: #Verse
   instanceVariableNames: 'stream'
   classVariableNames: ''
   poolDictionaries: ''

Each Verse will sing itself onto a Stream by singing its verse, then asking the next verse to sing itself.

   self singVerse.
   stream cr.
   self nextVerse sing

The recursion ends when you get to a Verse which represents a negative number of bottles of beer, the NegativeVerse. Many developers would have subclassed Verse to define NegativeVerse, but since it need only implement a single message, sing, and since there is no code sharing involved, I chose to subclass directly from object. This leaves me the option to factor Verse inheritance some other way, should that prove important in the future.

   subclass: #NegativeVerse
   instanceVariableNames: ''
   classVariableNames: ''
   poolDictionaries: ''
 NegativeVerse >>sing
   "Do nothing"

We will use other variations on Verse to capture the special cases in the song. PrecedingVerse will sing the Nth to second verse. PenultimateVerse will sing the verse in which there is one lonely bottle left, and UltimateVerse will sing that sad sad verse in which all the bottle are gone and their contents drained.

The Verse instance creation method is a Factory Method, returning a Verse of the correct subclass depending on the bottle count.

 Verse class>>Count: aninteger stream: aStream
   aninteger < 0 ifTrue: ^NegativeVerse new
   aninteger = 0 ifTrue: ^UltimateVerse stream: aStream.
   aninteger = 1 ifTrue: ^PenultimateVerse stream: aStream.
   ^(PrecedingVerse stream: aStream) setCount: aninteger

Singing a Verse

The singing of a Verse is represented by a method, each line of which causes the singing of one line of the song. In the future, it may be wise to further objectify the solution by creating a family of Line objects which sing individual lines . At this time, however, the solution does not seem to require this flexibility.

 Verse> >singVerse

The First Line

The first line is sung by singing the number of bottles, followed by "of bottles of beer on the wall".

   self countBottles.
   nextPutAll: ' of beer on the wall';

The count of bottles of beer is sung by singing the number of bottles, followed by a space and the word "bottle", appropriately pluralized:

     nextPutAll: self bottleCountString;
     nextPutAll: self bottlesString

The default implementation of bottleCountString prints the number of bottles in the receiver:

   ^self count printString

On the last verse, however, the word "No" is printed, rather than a number. This is represented by overriding bottleCountString in UltimateVerse:


The pluralization of the word "bottle" is handled by implementing the default plural version in Verse, and overriding in PenultimateVerse:


Counting and the Various Verses The count of bottles is explicitly represented by an instance variable in PrecedingVerse:

 subclass: #PrecedingVerse
 instanceVariableNames: 'count'
 poolDictionaries: ''

 PrecedingVerse>>setCount: aninteger
   count := aninteger

The other verses, subclasses of Verse with no additional instance variables, represent their counts implicitly in the accessing method for "count":


Succeeding Lines

The second line is computed in much the same way as the first.

   self countBottles.
    nextPutAll: ' of beer';

The third line shows variation in both the last and second to last verses. All the other verses sing it with:

     nextPutAll: 'Take one down and pass it around';
     nextPutAll: 'Take it down and pass it around';
     nextPutAll: 'There are no more to pass

The final line is a bit strange. The last line of one verse is the same as the first line of the next, so the obvious implementation is to send "self nextVerse bottlesOfBeerOnTheWall". However, the result of sending nextVerse to an UltimateVerse is a NegativeVerse, which doesn't know how to bottlesOfBeerOnTheWall. We would either have to duplicate the code from UltimateVerse in NegativeVerse or somehow send a message back to the UltimateVerse. Instead, we explicitly encode the fact that the final two verses have the same last line by hiding it behind a concatenated message, nextVerseBottlesOfBeerOnTheWall. The default implementation is simple:

   self nextVerse bottlesOfBeerOnTheWall
 UltimateVerse overrides this to send itself the
 message bottlesOfBeerOnTheWall:
   self bottlesOfBeerOnTheWall


Instances of the subclasses of Verse are created by passing along the Stream to be sung on. This is not public protocol, however, and is intended to be used only by the Verse class>>count:on: method.

 Verse class>>Stream: aStream
   ^self new setStream: aStream
 Verse>>SetStream: aStream
   stream:= aStream

The next verse is computed by decrementing the count by one and sending it to the FactoryMethod in Verse:

     count: self count - 1
     stream: stream

Finally, Verse provides a convenient Facade to sing any number of verses:

 Verse class>>sing: aninteger
   writer := WriteStream on: String new.
     count: aninteger
     stream: writer) sing.
   ^writer contents


This program's use of a Stream for concatenation makes it generally efficient. Here is a performance profile run with Profile/V (you were just waiting for the commercial plug, weren't you) and gathered on the recursive call to Verse>>sing.

100% (177) Verse>>sing ...

88% (155) Verse>>SingVerse ...
:31% (54) Verse>>nextVerseBottlesOfBeerOnTheWall ...
: :25% (44) Verse>>bottlesOfBeerOnTheWall ...
: : :20% (35) Verse>>CountBottles ...
: : : :14% (25) Verse>>bottleCountString ...
: :5% (8) Verse>>nextVerse
:26% (46) Verse>>bottlesOfBeerOnTheWall ...
: :20% (35) Verse>>countBottles ...
: : :15% (26) Verse>>bottleCountString ...
:22% (39) Verse>>bottlesOfBeer .. .
: :18% (31) Verse>>countBottles .. .
: : :10% (18) Verse>>bottleCountString ...
:8% (15) Verse>>takeOneDown .. .
10% (17) Verse>>nextVerse .. .

NextVerse is redundantly computed twice, so its total of 15% could be cut in half. BottleCountString is computed three times, so its total could be cut from 39% to 13%. This could be further reduced by printing the bottle count directly on the stream, without creating an intermediate String.

Final Comments

With a bit of work, this program could be expanded to encompass a framework for singing repetitive songs of all kinds. At present, however, it stands as a monument to that sense of the ridiculous that is all that gets us through some times. Long may it wave.

Kent Beck

Scrum Is Hard!

Scrum is hard and there are some important things your Development Team needs to know how to do.

Continue reading

Welcome to Left Side Agile!

First a word about the name.  When our friends wrote the Agile Manifesto for Software Development they paired a series of values, e.g. individuals and interactions over processes and tools.  As I travel around the world helping people better understand Agile, I often find that more attention is  […]

Continue reading

Page top