C++ Bowling Kata Result 72
I’m teaching a TDD and Refactoring class this week using C++. Since I had not recently wrote the bowling kata in C++, I figured it was about time to do it again.
Unlike the previous Scala version, this one only addresses the happy-path. I do not consider throwing too many balls or scoring too many pins in any frame. However, having just written this in Scala, I’m sure I could do something similar in C++.
I just switched to CppUTest 2.0 and something I noticed is that if you use <vector> or other std-based classes, you need to make sure to include those first before including <CppUTest/TestHarness.h>. This is because CppUTest overloads new and delete, which causes havoc with the std-based classes. No big deal, I just made sure to include that file as the last header (rather than the first, which is what I used to do).
Here are the various files:RunAllTests.cpp
1 2 3 4 5 |
|
BowlingScoreCardTest.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
|
BowlingScoreCard.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
BowlingScoreCard.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
|
I sure do miss refactoring tools!-)
Scala Bowling Kata - still in the middle I suppose 90
"One more roll on a game with 20 rolls and an open 10th frame" should {
20 times { roll(1) }
roll(1) must throwA[IllegalArgumentException]
}
"Two more rolls a game with 10 spares" should {
10 times { spare }
roll(1)
roll(1) must throwA[IllegalArgumentException]
}
"Two marks in the 10th frame should" should {
18 times { roll(1) }
strike
spare
roll(1) must throwA[IllegalArgumentException]
}
On my flight from DFW to SNA, I got these behaviors implemented. The code was pretty ugly!
However, ugly code in hand, passing examples, a slight understanding of some of the problems with my code and a desire to make the BowlingScorer immutable was all I needed to make progress.
I removed the index instance field by rewriting the score method and injecting a tuple into foldLeft (written here using the short-hand notation /:): def scoreAt(frame:Int) =
((0,0) /: (1 to frame)) { (t, _) =>
(t._1 + scoreAtIndex(t._2), t._2 + incrementAt(t._2))
}._1
def onFirstThrow = {
var index = 0
while(index < rolls.length)
if(isStrike(index)) index += 1 else index += 2
index == rolls.length
}
While I am happy I was able to remove the index variable, which was really a parameter being passed around in a field (ugly), I am not happy with this method.
I changed the roll method to return a new instance of a BowlingScorer, making the bowling scorer immutable: def roll(roll:Int) = {
validate(roll)
new BowlingScorer(rolls ++ Array(roll))
}
So I think I’m still somewhere in the middle of working through this code. Again, I’m still learning Scala. I have a lot to learn. I really only barely understand functional programming and, frankly, the Eclipse IDE, while functional, is getting in the way quite a bit. So for a toy example it is OK. Given the choice of this environment or vi and the command line, I’d not pick the former. (I might give the other IDE’s a go, but that’s not really what I’m interested in learning right now.)
So here’s the next version. I plan to work through all of the comments I’ve yet to process from the previous blog posting over the next few days. If you can recommend a better implementation of onFirstThrow, I’d appreciate it.
Other general comments also welcome.
BowlingScorerExampleGroup.scala
package com.om.example
import org.specs._
object BowlingScorerExampleGroup extends SpecificationWithJUnit {
var scorer = new BowlingScorer(Nil);
def roll(value:Int) =
scorer = scorer.roll(value)
def haveAScoreOf(expected:Int) =
scorer.score must_== expected
def strike =
roll(10)
def spare {
roll(5)
roll(5)
}
implicit def intToDo(count: Int) = {
new {
def times(f: => Unit) = {
1 to count foreach { _ => f }
}
}
}
"A Newly Created Bowling Scorer" should {
haveAScoreOf(0)
}
"A game with all 0's" should {
20 times { roll(0) }
haveAScoreOf(0)
}
"A game with all 1's" should {
20 times { roll(1) }
haveAScoreOf(20)
}
"A game with a single spare followed by a 5" should {
spare
roll(5)
haveAScoreOf(20)
}
"A game with all 5's" should {
10 times { spare }
roll(5)
haveAScoreOf(150)
}
"A game with a single strike followed by a 4" should {
strike
roll(4)
haveAScoreOf(18)
}
"A game with a strike, spare then an open frame with two 3's" should {
strike
spare
2 times { roll(3) }
haveAScoreOf(39)
}
"A game with strike, spare then an open frame with two 3's" should {
spare
strike
2 times { roll(3) }
haveAScoreOf(42)
}
"A Dutch 200 game, Spare-Strike" should {
5 times {
spare
strike
}
spare
haveAScoreOf(200)
}
"A Dutch 200 game, Strike-Spare" should {
5 times {
strike
spare
}
strike
haveAScoreOf(200)
}
"A Perfect game" should {
12 times { strike }
haveAScoreOf(300)
}
"The score for each frame of a Perfect game, each frame" should {
12 times { strike }
1 to 10 foreach { frame => scorer.scoreAt(frame) must_== 30 * frame }
}
"An individaul roll of > 10" should {
roll(11) must throwA[IllegalArgumentException]
}
"An iniviaul roll of < 0" should {
roll(-1) must throwA[IllegalArgumentException]
}
"A frame trying to contain more than 10 pins" should {
roll(8)
roll(3) must throwA[IllegalArgumentException]
}
"One more roll on a game with 20 rolls and an open 10th frame" should {
20 times { roll(1) }
roll(1) must throwA[IllegalArgumentException]
}
"Two more rolls a game with 10 spares" should {
10 times { spare }
roll(1)
roll(1) must throwA[IllegalArgumentException]
}
"Two marks in the 10th frame should" should {
18 times { roll(1) }
strike
spare
roll(1) must throwA[IllegalArgumentException]
}
}
BowlingScorer.scala
package com.om.example
class BowlingScorer(rollsSoFar:List[Int]){
val rolls:List[Int] = rollsSoFar
def roll(roll:Int) = {
validate(roll)
new BowlingScorer(rolls ++ Array(roll))
}
def validate(roll:Int) {
if(invalidRoll(roll))
throw new IllegalArgumentException("Individaul rolls must be from 0 .. 10")
if(frameRollTooHigh(roll))
throw new IllegalArgumentException("Total of rolls for frame must not exceed 10");
if(willBeTooManyRolls)
throw new IllegalArgumentException("Game over, no more rolls allowed")
}
def invalidRoll(roll:Int) =
(0 to 10 contains(roll)) == false
def frameRollTooHigh(roll:Int) =
openScoreAt(indexToValidate) + roll > 10
def willBeTooManyRolls =
tenthRolled(indexOf10thFrame) && nextRollTooMany(indexOf10thFrame)
def tenthRolled(tenthIndex:Int) =
tenthIndex < rolls.length
def nextRollTooMany(tenthIndex: Int) =
allowedTenthFrameRolls(tenthIndex) < rollsInTenthFrame(tenthIndex) + 1
def indexOf10thFrame =
(0 /: (1 until 10)) {(c, _) => c + incrementAt(c)}
def allowedTenthFrameRolls(index:Int) =
if(isMark(index)) 3 else 2
def rollsInTenthFrame(index: Int) =
rolls.length - index
def indexToValidate =
if(onFirstThrow) rolls.length else rolls.length - 1
def onFirstThrow = {
var index = 0
while(index < rolls.length)
if(isStrike(index)) index += 1 else index += 2
index == rolls.length
}
def scoreAt(frame:Int) =
((0,0) /: (1 to frame)) { (t, _) =>
(t._1 + scoreAtIndex(t._2), t._2 + incrementAt(t._2))
}._1
def score = scoreAt(10)
def scoreAtIndex(index:Int) =
if(isMark(index)) markScoreAt(index) else openScoreAt(index)
def incrementAt(index:Int) =
if(isStrike(index)) 1 else 2
def isMark(index:Int) =
isStrike(index) || isSpare(index)
def isStrike(index:Int) =
valueAt(index) == 10
def markScoreAt(index:Int) =
sumNext(index, 3)
def isSpare(index:Int) =
openScoreAt(index) == 10 && valueAt(index) != 10
def openScoreAt(index:Int) =
sumNext(index, 2)
def sumNext(index:Int, count:Int) =
(0 /: (index until index+count))(_ + valueAt(_))
def valueAt(index:Int) =
if(rolls.length > index) rolls(index) else 0
}
Scala Bowling Kata - somewhere in the middle... 47
- Installed the Eclipse Scala Plugin
- Installed Scala using Mac Ports
- Figured out how to get those things playing nice (the plugin page pretty much did that, but in a nutshell, add a few jar files to the classpath)
- We don’t need YADT – Yet another damn term
- Trait is a heavily overloaded word
- I like the term BDD better and it fits.
Anyway, one such choice was Specs, which is what I decided to use.
So back to yak shaving:- I added another jar to my classpath in Eclipse
- Then read how to get it running in Eclipse. Not too bad, I suppose.
So now I need to learn Scala. Sure, I’ve used it, but far less than Ruby. So it took me several hours to get specs running along with writing some Scala code to score a game – I’m glad I know the domain at least.
I wanted to make similar behaviors to the ones I wrote for the Ruby version, which I did.
However, unlike the Ruby version, I was curious what would happen if I:- Took an approach similar to Uncle Bob – strikes take one slot in an array
- Added input validation
On the one hand, there are some interesting things I managed to create. On the other hand, I’ve got a bit of a mess. I have a stateful object to avoid passing parameters so that I can write some of the code cleanly. I know I need to add in an intermediate computational object, and I’m going to get to that. However, I wanted to get feedback on what I’ve put out there so far.
Specifically,- What do you think of the (bdd-style) examples from specc?
- What is the correct way to write the Times(20).Do( ...) thing I came up with, there has be a better way?
- For the part of the bowling scoring code that is not stateful (read this as, does not violate the SRP), what do you think of it?
- How would you remove most/all of the state (other than the individual rolls) out of the Bowling scorer class? (Or would you choose to have the roll() method return a new instance of BowlingScorer with the new score recorded?)
- Notice that the class maintains a mini state machine in the form of tracking whether the first ball of he current frame (not tracked) has or has not been thrown. That’s only there to be able to perform input validation. I considered:
- Walking the array
- Going to 2 slots for every frame (making it easy to find the frame)
- Storing a frame object (ok, I didn’t really consider it, but I did think about it)
- The mini state machine
- nextFrameScore uses the index instance variable, and changes it. This both violates command-query separation and demonstrates a violation of the SRP, but it made the scoreAt method look nice.
An interesting side effect is that scoring marks (strikes and spares) uses the same approach, sum up three rolls total.
I know this needs work. What I’ve got works according to its current specification (its examples), so in a sense, that’s a good thing because I’ve already stared experimenting with trying out different solutions. However, I am painfully aware of how unaware I am of Scala at the moment, so your (hopefully gentle) feedback will tell me what I need to learn next.
Looking forward to the virtual beating …
Brett
Here are the two files I’ve created so far (and to be clear, all of the examples pass): BowlingScorerExampleGroup.scalapackage com.om.example
import org.specs._
object BowlingScorerExampleGroup extends SpecificationWithJUnit {
var scorer = new BowlingScorer();
def roll(value:Int) {
scorer.roll(value)
}
def rollMany(rolls:Int, value:Int) {
0.until(rolls).foreach { arg => scorer.roll(value) }
}
def haveAScoreOf(expected:Int) {
scorer.score must_== expected
}
def strike {
roll(10)
}
def spare {
rollMany(2, 5)
}
abstract class IDo {
def Do(block: => Unit)
}
def Times(count:Int): IDo = {
return new IDo {
def Do(block: => Unit) {
1.to(count).foreach( arg => block )
}
}
}
"A Newly Created Bowling Scorer" should {
haveAScoreOf(0)
}
"A game with all 0's" should {
Times(20).Do( roll(0) )
haveAScoreOf(0)
}
"A game with all 1's" should {
Times(20).Do { roll(1) }
haveAScoreOf(20)
}
"A game with a single spare followed by a 5" should {
spare
roll(5)
haveAScoreOf(20)
}
"A game with all 5's" should {
Times(10).Do( spare )
roll(5)
haveAScoreOf(150)
}
"A game with a single strike followed by a 4" should {
strike
roll(4)
haveAScoreOf(18)
}
"A game with a strike, spare then an open frame with two 3's" should {
strike
spare
Times(2).Do( roll(3) )
haveAScoreOf(39)
}
"A game with strike, spare then an open frame with two 3's" should {
spare
strike
Times(2).Do( roll(3) )
haveAScoreOf(42)
}
"A Dutch 200 game, Spare-Strike" should {
Times(5).Do {
spare
strike
}
spare
haveAScoreOf(200)
}
"A Dutch 200 game, Strike-Spare" should {
Times(5).Do {
strike
spare
}
strike
haveAScoreOf(200)
}
"A Perfect game" should {
Times(12).Do( strike )
haveAScoreOf(300)
}
"The score for each frame of a Perfect game, each frame" should {
Times(12).Do( strike )
1.to(10).foreach{ frame => scorer.scoreAt(frame) must_== 30 * frame }
}
"An individaul roll of > 10" should {
roll(11) must throwA[IllegalArgumentException]
}
"An iniviaul roll of < 0" should {
roll(-1) must throwA[IllegalArgumentException]
}
"A frame trying to contain more than 10 pins" should {
roll(8)
roll(3) must throwA[IllegalArgumentException]
}
}
BowlingScorer.scala
package com.om.example
class BowlingScorer {
var rolls:Array[Int] = Array()
var index:Int = 0
var firstBallInFrameThrown: Boolean = false;
def roll(roll:Int) = {
validate(roll)
record(roll)
}
def validate(roll:Int) {
if((0).to(10).contains(roll) == false)
throw new IllegalArgumentException("Individaul rolls must be from 0 .. 10")
if(openScoreAt(indexToValidate) + roll > 10)
throw new IllegalArgumentException("Total of rolls for frame must not exceed 10");
}
def record(roll: Int) {
rolls = rolls ++ Array(roll)
firstBallInFrameThrown = firstBallInFrameThrown == false && roll != 10
}
def indexToValidate = {
if(firstBallInFrameThrown) rolls.length - 1 else rolls.length
}
def scoreAt(frame:Int) = {
1.to(frame).foldLeft(0) { (total, frame) => total + nextFrameScore }
}
def score = {
scoreAt(10)
}
def nextFrameScore = {
var result = 0;
if(isStrike(index)) {
result += markScoreAt(index)
index += 1
} else if(isSpare(index)) {
result += markScoreAt(index);
index += 2
} else {
result += openScoreAt(index);
index += 2
}
result
}
def isStrike(index:Int) = {
valueAt(index) == 10
}
def markScoreAt(index:Int) = {
sumNext(index, 3)
}
def isSpare(index:Int) = {
openScoreAt(index) == 10
}
def openScoreAt(index:Int) = {
sumNext(index, 2)
}
def sumNext(index:Int, count:Int) = {
index.until(index+count).foldLeft(0)(_ + valueAt(_))
}
def valueAt(index:Int) = {
if(rolls.length > index) rolls.apply(index) else 0
}
}
Bowling Game Kata in Ruby 62
I have not really used Ruby much. I’ve written a few tutorials, messed around with RSpec and Test::Unit and even Rails a bit, but I really don’t know Ruby that well. I get Ruby (the MOP, instances, blocks, open classes, ...) but there’s a difference between understanding that stuff and using it day-to-day.
Last night we had a Dojo in Oklahoma City and I wanted to get refreshed with RSpec, so I decided to jump in and do the bowling game kata. I did not follow uncle bob’s lead exactly. For one, I went ahead and stored two throws for each frame. While what he ends up with is a bit shorter, it bothers me a little bit. I’ve also seen people surprised by how bob stores his scores, so in a sense it violates the law of least astonishment.
That’s neither here nor there, I got it working just fine – though handling strikes was a bit more difficult because I decided to store two rolls instead of one (so clearly, there’s no best answer, just ones that suck for different reasons).
After my first go around, I had a single spec with examples all under a single describe (what’s that term they’d use for what the describe expression creates?). I added several examples for partial scores, to make sure I was handling incomplete games correctly. I restructured those a bit and tried to make the names a bit more clear, not sure if I was successful.
In my original version I started with a frame in the score method as a local variable, but it quickly got converted to an index, and the index was mostly passed around after that. The approach was very c-esque. I didn’t like that index all over the place, so I tried to remove it by refactoring. It took several false starts before I bit the bullet and simply duplicated each of the methods, one at a time, using parallel development. The old version using an index, the new one use a 1-based frame number. After I got that working with frames, I removed most of the methods using an index, except for a few.
What follows is the spec file and the ruby class. If you read the names of some of the examples, you might think I used to bowl in league, I did. My average was a paltry 158, my best game ever a 248. Best split I ever picked up? 4, 6, 7, 10.
Comments welcome.
bowling_score_card_spec.rb
require 'bowling_score_card'
describe BowlingScoreCard do
before(:each) do
@bowling_game_scorer = BowlingScoreCard.new
end
def roll value
@bowling_game_scorer.roll value
end
def roll_many count, value
count.times { roll value }
end
def score_should_be value
@bowling_game_scorer.score.should == value
end
it 'should score 0' do
score_should_be 0
end
describe 'Scores for Complete Games' do
it 'should score 0 for an all gutter game' do
roll_many 20, 0
score_should_be 0
end
it 'should show 20 for an all 1 game' do
roll_many 20, 1
score_should_be 20
end
it 'should score game with single spare correctly' do
roll_many 3, 5
roll_many 17, 0
score_should_be 20
end
it 'should score game with single strike correctly' do
roll 10
roll 5
roll 2
roll_many 17, 0
score_should_be 24
end
it 'should score a dutch-200, spare-strike, correclty' do
10.times do
roll_many 2, 5
roll 10
end
roll_many 2, 5
score_should_be 200
end
it 'should score a dutch-200, strike-spare, correctly' do
10.times do
roll 10
roll_many 2, 5
end
roll 10
score_should_be 200
end
it "should score all 5's game as 150" do
roll_many 21, 5
score_should_be 150
end
it 'should score a perfect game correctly' do
roll_many 12, 10
score_should_be 300
end
it 'should not count a 0, 10 roll as a strike' do
roll 0
roll 10
roll_many 18, 1
score_should_be 29
end
end
describe 'Scoring for open games' do
it 'should score just an open frame' do
roll 4
roll 3
score_should_be 7
end
it 'should score just a spare' do
roll_many 2, 5
score_should_be 10
end
it 'should score partial game with spare and following frame only' do
roll_many 3, 5
score_should_be 20
end
it 'should score an opening turkey correctly' do
roll_many 3, 10
score_should_be 60
end
end
describe 'Scoring open game starting with a srike' do
before(:each) do
roll 10
end
it 'should score partial game with only strike' do
score_should_be 10
end
it 'should score partial game with strike and half-open frame' do
roll 4
score_should_be 18
end
it 'should score partial game with strike and open frame' do
roll 3
roll 6
score_should_be 28
end
it 'should score partial game with strike and spare' do
roll 3
roll 7
score_should_be 30
end
end
describe 'Open game starting with two Strikes' do
before(:each) do
roll 10
roll 10
end
it 'should have a score of 30' do
score_should_be 30
end
it 'should score correctly with following non-mark' do
roll 4
score_should_be 42
end
it 'should score correclty with third frame open' do
roll 4
roll 3
score_should_be 48
end
end
end
bowling_score_card.rb
class BowlingScoreCard
def initialize
@rolls = []
end
def roll value
@rolls << value
@rolls << 0 if first_throw_is_strike?
end
def score
(1..10).inject(0) { |score, frame| score += score_for frame }
end
def score_for frame
return strike_score_for frame if is_strike_at? frame
return spare_score_for frame if is_spare_at? frame
open_score_for frame
end
def first_throw_is_strike?
is_first_throw_in_frame? && @rolls.last == 10
end
def is_first_throw_in_frame?
@rolls.length.odd?
end
def open_score_for frame
first_throw_for(frame) + second_throw_for(frame);
end
def spare_score_for frame
open_score_for(frame) + first_throw_for(next_frame(frame))
end
def strike_score_for frame
score = open_score_for(frame) + open_score_for(next_frame(frame))
if is_strike_at? next_frame(frame)
score += first_throw_for(next_frame(next_frame(frame)))
end
score
end
def next_frame frame
frame + 1
end
def is_spare_at? frame
(open_score_for frame) == 10 && is_strike_at?(frame) == false
end
def is_strike_at? frame
first_throw_for(frame) == 10
end
def first_throw_for frame
score_at_throw(index_for(frame))
end
def second_throw_for frame
score_at_throw(index_for(frame) + 1)
end
def index_for frame
(frame - 1) * 2
end
def score_at_throw index
@rolls.length > index ? @rolls[index] : 0
end
end
Notes from the OkC Dojo 2009-09-30 69
Tonight we had a small group of die-hard practitioners working with Ruby and RSpec. We intended to use the Randori style, but it was a small enough group that we were a bit more informal than that.
We tried the Shunting Yard Algorithm again and it worked out fairly well. The level of experience in Ruby was low to moderate (which is why we wanted to get people a chance to practice it) and the RSpec experience was generally low (again, great reason to give it a try).
- Forth
- Operator precedence
- Operator associativity
- L-Values and R-Values
- Directed Acyclic Graphis
- In-fix, pre-fix, post-fix binary tree traversal
- Abstract Syntax Trees (AST)
- The list goes on, I’m a big-time extrovert, so I told Chad to occasionally tell me to shut the heck up
- 1 + 3 becomes 1 3 +
- a = b = 17 becomes a b 17 = =
- 2 + 3 * 5 becomes 2 3 5 * +
- 2 * 3 + 5 becomes 2 3 * 5 +
One typical approach to this problem is to develop an AST from the in-fix representation and then recursively traversing the AST using a recursive post-fix traversal.
What I like about he Shunting Yard Algorithm is it takes a traditionally recursive algorithm (DAG traversal, where a binary tree is a degenerate DAG) and writes it iteratively using it’s own stack (local or instance variable) storage versus using the program stack to store activation records (OK stack frames). Essentially, the local stack is used for pending work.
This is one of those things I think is a useful skill to learn: writing traditionally recursive algorithms using a stack-based approach. This allows you to step through something (think iteration) versus having to do things whole-hog (recursively, with a block (lambda) passed in). In fact, I bought a used algorithm book 20 years ago because it had a second on this subject. And looking over my left shoulder, I just saw that book. Nice.
To illustrate, here’s the AST for the first example:
Since the group had not done a lot with recursive algorithms (at least not recently), we discussed a short hand way to remember the various traversal algorithms using three letters: L, R, P
- L -> Go Left
- R -> Go Right
- P -> Print (or process)
- in-fix, in -> in between -> L P R
- pre-fix, pre, before -> P L R
- post-fix, post, after -> L R P
- in-fix: Go left, you hit the 1, it’s a leaf note so print it, go up to the +, print it, go to the right, you end up with 1 + 3
- post-fix: Go left you hit the 1, it’s a leaf node, print it, go back to the +, since this is post-fix, don’t print yet, go to the right, you get the 3, it’s a leaf node, print it, then finally print the +, giving: 1 3 +
- pre-fix: start at + and print it, then go left, it’s a leaf note, print it, go right, it’s a leaf node, print it, so you get: + 1 3 – which looks like a function call (think operator+(1, 3))
It’s not quite this simple – we actually looked at larger examples – but this gets the essence across. And to move from a tree to a DAG, simply iterate over all children, printing before or after the complete iteration; in-fix doesn’t make as much sense in a general DAG. We also discussed tracking the visited nodes if you’ve got a graph versus an acyclic graph.
After we got a multi-operator expression with same-precedence operators working, e.g., 1 + 3 – 2, which results in: 1 3 + 2 -, we moved on to handling different operator precedence.
Around this time, there was some skepticism that post-fix could represent the same expression as in-fix. This is normal, if you have not seen these kinds of representations. And let’s be frank, how often do most of us deal with these kinds of things? Not often.
Also, there was another question: WHY?
In a nutshell, with a post-fix notation, you do not need parentheses. As soon as an operator is encountered, you can immediately process it rather than waiting until the next token to complete the operator (no look-ahead required). This also led to HP developing a calculator in 1967 (or ‘68) that was < 50 pounds and around USD $5,000 that could add, subtract, multiply and divide, which was huge at the time (with a stack size of 3 – later models went to a stack size of 4, giving us the x, y, z and t registers).
During this rat-hole, we discussed associativity. For example, a = b = c is really (a = (b = c))
That’s because the assignment operator is right-associative. This lead into r-values and l-values.
Anyway, we’re going to meet again next week. Because we (read this as me) were not disciplined in following the Randori style, these side discussions lead to taking a long to fix a problem. We should have “hit the reset button” sooner, so next time around we’re going to add a bit more structure to see what happens:- The driver finishes by writing a new failing test.
- The driver commits the code with the newest failing test (we’ll be using git)
- Change drivers and give him/her some time-box (5 – 10 minutes)
- If, at the end of the current time-box, the current driver has all tests passing, go back to the first bullet in this list.
- If at the end, the same test that was failing is still failing, (fist time only) give them a bit more time.
- However, if any other tests are failing, then we revert back to the last check in and switch drivers.
Here’s an approximation of these rules using yuml.me:
(start)->(Create New Failing Test)->(Commit Work)->(Change Drivers) (Change Drivers)->(Driver Working) (Driver Working)-><d1>[tick]->(Driver Working) <d1>[alarm]->(Check Results)->([All Tests Passing])->(Create New Failing Test) (Check Results)->([Driver Broke Stuff])->(git -reset hard)->(Change Drivers) (Check Results)->([First Time Only and Still Only Newest Test Failing])->(Give Driver A Touch More Time)->(Check Results)
Note that this is not a strict activity diagram, the feature is still in beta, and creating this diagram as I did made the results a bit more readable. Even so, I like this tool so I wanted to throw another example in there (and try out this diagram type I have not used before – at least not with this tool, I’ve created too many activity diagrams). If you’d like to see an accurate activity diagram, post a comment and I’ll draw one in Visio and post it.
Anyway, we’re going to try to move to a weekly informal practice session with either bi-weekly or monthly “formal” meetings. We’ll keep switching out the language and the tools. I’m even tempted to do design sessions – NO CODING?! What?! Why not. Some people still work that way, so it’s good to be able to work in different modes.
If you’re in Oklahoma City, hope to see you. If not, and I’m in your town, I’d be interested in dropping into your dojos!
What's your favorite Kata? 72
I’m looking to collect several katas for the OkC CoCo Dojo to make sure we have plenty of future practice sessions already in place. Ultimately I want it to be at least bi-weekly (or weekly) and self sustaining. Along those lines, I’d like to hear what are your favorite katas.
I’d prefer you mention things you’ve tried yourself. Please post links and your impressions in response to the blog. I’ll collect them here, and let me know if you’d like me to credit you with pointing me to the idea (or for the idea itself if you created it).
FWIW, after a little thinking, my favorite kata based on the number of times I’ve used it in one manner or another is Monopoly®.
Another Kata: Expression Tokenizer 76
I continue to work on some examples for upcoming kata’s at the OkC CoCo. The next problem (previously mentioned here) is an implementation of the Shunting Yard Algorithm.
This past week I used that with a group in North Carolina and I discovered that it was much easier to tokenize the expression as I worked my way through it rather than attempt to make it easy to split into tokens up front.
I worked through just this smaller problem of converting an expression into tokens using the iterator pattern a few times and eventually got what I thought was a pretty good solution. I was wrong, I got it even tighter by making more appropriate use of the regular expression libraries in Java. (This is an example of where my regex mental model – based primarily on grep, vi and AWK – was inadequate when taking into consideration typical implementations of regex libraries with classes like Pattern and Matcher.)
Anyway, here’s a writeup for that Kata: http://schuchert.wikispaces.com/Katas.ExpressionTokenizer.
My final version turned into something crazy-short. I did not anticipate the final version. Part of it, as mentioned above, had to do with how I previously envisioned using regular expressions. Part of it might have been that it just took a few times for the patterns naturally occurring to become evident to me. In any case, working through this problem three times resulted in the following revelations:- Initially I though it would be hard, it was not and in fact much less work than what I was doing in the original problem. And it took a lot less time than I expected.
- The second time around I was looking to duplicate the experience, which I did. But I saw quite a bit of improvement.
- The final version was really an a-ah for me. Initially it was just like the second version. Then, once I had the tests in the kata written, I started messing around, looking for additional improvements (and heavily applying the DRY principle). I found them, exploited commonality and finally I got to the point where there was one thing I did not like, and fixing that led to a huge improvement, which led to a few more significant improvements.
Ultimately, I’ll have several useful take-aways from working on the problem several times.
If you’d like to see the “latest final version” of this, ping me. I’ll consider posting it to the blog, but I’d rather not give anything away without a specific request.
Shunting Yard Algorithm Kata 71
Next week (end of June 2009) I hoping to schedule the second OkC CoCo Dojo. The first Dojo was fun with a decent turnout. However, it was a bit “loose” (my fault). Loose is fine, but this time around I want to try a different approach and see how that works out.
The problem for this second Dojo is: http://schuchert.wikispaces.com/Katas.ShuntingYardAlgorithm.
In this second Dojo, we will start with several examples with their expected results already written, as well as a link to an algorithm. The goal is to make it through as many examples as possible (in the order listed) in the time allotted.
Unlike the first Dojo where there was a brief problem description and I sort of served as a customer, in this case we have a documented algorithm and a series of examples that:
- Explicitly define desired results
- Are written in a particular order to make it easy to grow the algorithm without having to take large steps
If you want to give this a try, the link above has the description I’ll be starting with.
Comments welcome!