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
describe “something” {} => ExampleGroup
I don’t know Ruby, and therefore, RSpec, but now I know what the “it” keyword is. B-)
My only concern is that the word “kata” is used when there is no form being followed. Uncle Bob’s Bowling kata is specifically in Java. You are trying to follow along with the spirit, but as you are not using the same language (the same form) and especially because you diverged in approach, it’s no longer a kata, right?
It’s an exercise. It’s good for developing your skill as a programmer, but until there is a form you follow precisely and accurately, calling it a kata seems like a misnomer to me. I know in programming circles that there are plenty of things called katas that aren’t what I say they should be, but is this just something to accept, or should there be a push for katas to be things that a programmer should be able to follow step-by-step?
Thanks David, too damn obvious for my knuckle head!
GB, as for whether or not it is a kata, I think it is. I did practice it. I did work with many of the same tests that bob used. I took advantage of some of the tricks I’ve picked up from the bdd community (in this example, only a few).
That I did not go with the same solution, I think, is good.
In fact, I started with the same solution, then I tried changing it around. Then when I thought I could score complete and incomplete games correctly, I spent time looking at different ways to write things. I messed around with it.
Kata is defined as “choreographed patterns of movements practiced either solo…” (according to wikipedia). Given that, I did use the bowling game example to practice using RSpec. I’ve done the bowling kata as bob does it in Java (and C# and I think I might have done it once in C++).
So now the questions is this, to what, precisely, does the word kata apply? It is the practice of writing a test, getting it to pass, refactoring, or is the particular problem?
I see your take on the word. I don’t hold the same definition. It’s quite possible my definition is wrong, but I’m going to stick to it until I’m convinced otherwise. FWIW, I’ve practiced forms in martial arts. In that case, the sequence of steps was the practice. So I grok the idea, I’m just not sure how direct I want to interpret the metaphor.
Brett, I’m confused by the example “it should score a dutch-200, strike-spare, correctly”. It looks like you’re rolling 31 times (10*(2+1)+1). I’m not a bowler, but it looks to me like you are playing 21 frames which surely must be too much?
Regarding the use of the word “kata”, I think it is correct. A programming kata is not the exakt same thing as a martial arts kata. In the latter, the point is to do the exact same thing every time, with total precision and focus. Ideally, if you’d superimpose two video recordings of a master performing a kata on two different days, you’d never know that there were two recordings. If we did a programming kata the same way, we’d strive to end up with the exact same code written in the exact same order and pace. I don’t think that would be useful (but I’m willing to be proven wrong).
Instead, the programming kata (in my mind) borrows the purpose and confinements (if that’s the best word) from the martial arts kata. The purpose is to hone and perfect our basic moves (creating test cases/specs, doing the red-green-refactor dance, doing the simplest thing that works, etc). The confinements, as I see it, is that you should be able to perform the kata without external references. If you need to look up commands or regexp syntax or anything that a programmer at some level knows about the language, the kata is above your current level. And if you need to look up the rules for bowling scoring, you have not prepared for the kata. A kata is not a time to learn new things, but to practise and hone what you know.
@Brett,
thanks to your post I finally got round to trying a BDD tool.
I took your specification, turned Ruby into Groovy, trivially turned RSpec syntax into easyb syntax, and then run it against the Java code I wrote some time ago for a Bowling Kata: the only behaviours that failed where the two dutch-200 ones, which I need to investigate, possibly in the light of what David Vrensk said in the previous comment.
Here is the translated specification:
David Vrensk wrote:
Do’h! David, you are correct, I am rolling too many frames. It works because of the score method (and the fact that alternating spares or strikes will result in 200 and both approaches fill up the available score slots):
I only score 10 frames, so the extra “crap” is ignored. In both of my dutch-200 games I should have 5.times …, not 10.
I had not yet added negative cases:I’ll leave the errors in the blog, but I’ll fix my code by adding code to validate the input, those tests will fail, then I’ll fix the tests.
Great example of why having a navigator is good.
Philip Schwarz wrote:
Yep, as David mentioned, the examples are wrong. See post just above this one. And cool seeing easyb. Thanks for showing us that.Rolled one too many (17—> 16). Makes sense I supose.
Next, I added several more negative examples than expected: Ultimately, I ended up with a bit of changed code (and one ugly method:As you can probably guess, the should_allow_roll? method is a bit cryptic. In addition to it being long and full of magic numbers, it also has the mythical 11th frame, which is a side-effect of not handling the 10th frame as special.
On the other hand, the score card hides all of this, so before I say this is truly bad, I need to go back to uncle bob’s solution and add in the same negative examples and see how well it grows.
Here is the full source of the results: bowling_score_card_spec.rbbowling_score_card.rb
And finally, here’s the output from running spec at the command line (minus the coloring):
It works great. Thanks
Works great
The access was actual c-esque. I didn’t like that basis all over the place, so I approved to abolish it by refactoring. It took several apocryphal starts afore I bit the ammo and artlessly bifold anniversary of the methods, one at a time, application alongside development. The old adaptation application an index, the new one use a 1-based anatomy number. Thank you so much for sharing details about game.
I started with a anatomy in the account adjustment as a bounded variable, but it bound got adapted to an index, and the basis was mostly anesthetized about afterward that. The access was actual c-esque. I didn’t like that basis all over the place, so I approved to abolish it by re-factoring.
Nice post.
Thanks for sharing.
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. cheap VPS 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.
Good topic.Thanks for sharing! It really helpful to me about those information!!
Thank you for this nice post
my blogs : calories in food | how to put on a condom
Thank you for this nice post
my blogs : how to finger a girl | how to eat a girl out
If you mean to find great shoes for your children puma speed trainers also provides a mixture of finicky and affordable shoes for them. There are a lot of choices, it is up ring call,Ugg Boots, after by people that indigence an incredible quantity of column. This will make the customers happier. If you are often tangled in Singapore womens puma future cat shoes sale at Sainte Marie that could enhance operational efficiency, range visibility and turnaround time,” said Desmond Chan, managing boss, South Asia, Menlo Worldwide Logistics. “Our multi-client facility in Boon Lay Way provides puma trainers with different flag. puma uk’s youngest targets are toddlers. The puma for sale shoes are incredibly affordable, yet they still hold the grace. Wearing comfortable shoes will help children exploit better.
white iphone 4 available now. It is the best news today.
and a small amount replica panerai watches amount of brain and doesn’t go directly armani sport watches directly through the whole brain is one Hermes scarf one case,” said
Thanks for shareing! I agree with you. The artical improve me so much! I will come here frequently. Would you like to banckup iphone SMS to mac, macBook, macbookPro as .txt files? Now a software iphone SMS to Mac Backup can help you to realize it.
iPad to Mac Transfer can help you transfer music, movie, photo, ePub, PDF, Audiobook, Podcast and TV Show from ipad to mac freely.
Your site is amazing.I am very impressed to see this,i want to come back for visiting your site.Keep doing Good as well as you can.
Amazing post. Love the ideas.
We are the professional t-shirts manufacturer. t-shirts supplier. t-shirts factory, custom t-shirts.
Almost any situation--good or bad --is affected by the attitude we bring to. Adversity reveals genius; fortune conceals it. As fruit needs not only sunshine but cold nights and chilling showers to ripen it, so character needs not only joy but trial and difficulty to mellow it. Although the world is full of suffering, it is full also of the overcoming of it. tiffany and co outlet
Thank you for this nice post
While searching for “flash game” on Google I found your blog, read your article, along with many concepts like you, I thank to you
Game is an eternal theme that everyone likes. Thanks very much the blog, wish you good health to write better and more
Your blog has many interesting, nice words of thanks be sent to you
Love game day
Thanks it’s very help me
nice post.
internette görüntülü olarak okey oyunu oyna, gerçek kisilerle tanis, turnuva heyecanini yasa.
thanks for this blog,, nice ideas.
oh so nice blog and good idea,, maybe you should visit on my website too.. thanks a lot.
i love the article so nice and very informative.
wow!!! amazing ideas.. i found your blogs in google and it is so awesome very useful and informative,, try to visit my website too. thanks a lot God bless :)
wow!!! amazing ideas.. i found your blogs in google and it is so awesome very useful and informative,, try to visit my website too. thanks a lot God bless :)
hey, amazing blog with all the things i learn here.
I visited this page first time and found it Very Good Job of acknowledgment and a marvelous source of info…......Thanks Admin!
For people that adore music, i suggest the monster powerbeats sport headphones to you, Just Beats Studio Purple has three color, red, whit and black. It is significant efficacy on this monster diddybeats in-ear headphones.
What a wonderful article! And are doing well on the whole, but their work also has shortcomings.
great ruby discussion…
I visited this page first time and found it Very Good Job of acknowledgment and a marvelous source of info……...Thanks Admin!
What a wonderful article! And are doing well on the whole, but their work also has shortcomings.
I didn’t know that this is possible in Ruby. I have to try this out.
Frequently Project Manager Job Description I am searching the great info is visible in Legal Secretary Job Description this blog and using the nice technology in this blog Medical Transcriptionist Job Description This is really superb info is visible in this blog and really great technology in this blog and using Paralegal Job Description the nice services in this blog
asdas df+8s99s9sss
asdfs d9gh8f7h7f74f444
asas df+9s9s9sss
gooood article
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.
If you hide it. will the code run very well? it is worth thinking twice.
Thanks for the information, I’ll visit the site again to get update information online shopping
Bowling Game Kata in Ruby 54 good post61
Bowling Game Kata in Ruby 55 hoo,good article!!I like the post!176
Intertech Machinery Inc. provides the most precise Plastic Injection Mold and Rubber Molds from Taiwan. With applying excellent unscrewing device in molds,
Intertech is also very professional for making flip top Cap Molds in the world. Mold making is the core business of Intertech (Taiwan). With world level technology, Intertech enjoys a very good reputation for making Injection Mold and Plastic Molds for their worldwide customers.
This “average” report on the Wonderlic Analyze can be a Thirty, that is traditionally shown to characterize baseball hats the IQ of around Hundred. This kind of scores shows the exam taker might supply the correct solution for 20 of your 55 published multiple-choice concerns expected throughout the A dozen a matter of minutes helped. The particular hardest score in reported heritage involving test takers for the Football Merge at this point is assigned to original LSU cornerback and high level Next year Nba Draft potential customer Morris Claiborne, who seem to said to be have scored a new 5.
Thank’s U for this nice post for games.
Thanks a gain.
With more than 20 years of experience, Intertech provides an extensive integrated operational ability from design to production of molds 100% made in Taiwan. Additional to our own mold making factory, we also cooperate with our team vendors to form a very strong working force in Taiwan.
For the overseas market, we work very closely with local representatives in order to take care of the technical communication and after-sales service to our customers. We also participate in the EUROMOLD & FAKUMA exhibitions and meet our customers every year in Europe. By concentrating on mold “niche markets”, we play a very useful mold maker role from the Far East whenever customers want to develop their new projects. We provide services from A to Z to our customers on a very economic cost and effect basis.
beats by dre headphone vivienne westwood Melissa chirstian louboutin sale michael kors outlet store vivienne westwood handbags
michael kors outlet storeThe newly elected President of Egypt Morsy muhammad published the first speech since his victory over ahmed ShaFei g announced on Sunday night, vowed to “protect the international agreement and obligations”, this seems to be a reference of the peace treaty with Israel..chirstian louboutin outlet
vivienne westwood melissa Morsy tried to appease those worried that he will take immediate action to change the whole Egypt, is expected to become the President all the egyptians, “muslims, christians, old people, children, women and men, farmers, teachers, workers, those engaged in the private and public sectors, the businessmen.”beats by dre headphone
michael kors clearance bags Morsy welcome Obama’s support, the two leaders reaffirm their dedicated to advancing US-Egypt partnership, agreed to maintain close contact with the future of a few weeks, months, according to the statement. Christian Louboutin Daffodile 160mm Pumps
Thanks for sharing these items