<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Object Mentor Blog: Bowling Game Kata in Ruby</title>
    <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>Bowling Game Kata in Ruby</title>
      <description>&lt;p&gt;I have not really used Ruby much. I&amp;#8217;ve written a few tutorials, messed around with RSpec and Test::Unit and even Rails a bit, but I really don&amp;#8217;t know Ruby that well. I get Ruby (the &lt;span class="caps"&gt;MOP&lt;/span&gt;, instances, blocks, open classes, ...) but there&amp;#8217;s a difference between understanding that stuff and using it day-to-day.&lt;/p&gt;


	&lt;p&gt;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&amp;#8217;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&amp;#8217;ve also seen people surprised by how bob stores his scores, so in a sense it violates the law of least astonishment.&lt;/p&gt;


	&lt;p&gt;That&amp;#8217;s neither here nor there, I got it working just fine &amp;#8211; though handling strikes was a bit more difficult because I decided to store two rolls instead of one (so clearly, there&amp;#8217;s no best answer, just ones that suck for different reasons).&lt;/p&gt;


	&lt;p&gt;After my first go around, I had a single spec with examples all under a single describe (what&amp;#8217;s that term they&amp;#8217;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.&lt;/p&gt;


	&lt;p&gt;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&amp;#8217;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.&lt;/p&gt;


	&lt;p&gt;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.&lt;/p&gt;


	&lt;p&gt;Comments welcome.&lt;/p&gt;


	&lt;p&gt;&lt;i&gt;&lt;b&gt;bowling_score_card_spec.rb&lt;/i&gt;&lt;/b&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;bowling_score_card&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="constant"&gt;BowlingScoreCard&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:each&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
        &lt;span class="attribute"&gt;@bowling_game_scorer&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;BowlingScoreCard&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;roll&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;
        &lt;span class="attribute"&gt;@bowling_game_scorer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;roll_many&lt;/span&gt; &lt;span class="ident"&gt;count&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;
        &lt;span class="ident"&gt;count&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;score_should_be&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;
        &lt;span class="attribute"&gt;@bowling_game_scorer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;score&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score 0&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
        &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Scores for Complete Games&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score 0 for an all gutter game&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;20&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should show 20 for an all 1 game&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;20&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;20&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score game with single spare correctly&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;3&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;5&lt;/span&gt;
            &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;17&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;20&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score game with single strike correctly&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;5&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;2&lt;/span&gt;
            &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;17&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;24&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score a dutch-200, spare-strike, correclty&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="number"&gt;10&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
                &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;5&lt;/span&gt;
                &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
            &lt;span class="keyword"&gt;end&lt;/span&gt;
            &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;5&lt;/span&gt;

            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;200&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score a dutch-200, strike-spare, correctly&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="number"&gt;10&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
                &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
                &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;5&lt;/span&gt;
            &lt;span class="keyword"&gt;end&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;200&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;should score all 5's game as 150&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;21&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;5&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;150&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score a perfect game correctly&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;12&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;300&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should not count a 0, 10 roll as a strike&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
            &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;18&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;29&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Scoring for open games&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score just an open frame&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;4&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;3&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;7&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score just a spare&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;5&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score partial game with spare and following frame only&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;3&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;5&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;20&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score an opening turkey correctly&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll_many&lt;/span&gt; &lt;span class="number"&gt;3&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;60&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Scoring open game starting with a srike&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
        &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:each&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score partial game with only strike&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score partial game with strike and half-open frame&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;4&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;18&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score partial game with strike and open frame&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;3&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;6&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;28&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score partial game with strike and spare&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;3&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;7&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;30&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Open game starting with two Strikes&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
        &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:each&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should have a score of 30&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;30&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score correctly with following non-mark&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;4&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;42&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;

        &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;should score correclty with third frame open&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;4&lt;/span&gt;
            &lt;span class="ident"&gt;roll&lt;/span&gt; &lt;span class="number"&gt;3&lt;/span&gt;
            &lt;span class="ident"&gt;score_should_be&lt;/span&gt; &lt;span class="number"&gt;48&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;


	&lt;p&gt;&lt;i&gt;&lt;b&gt;bowling_score_card.rb&lt;/i&gt;&lt;/b&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;BowlingScoreCard&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;
        &lt;span class="attribute"&gt;@rolls&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[]&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;roll&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;
        &lt;span class="attribute"&gt;@rolls&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;
        &lt;span class="attribute"&gt;@rolls&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;first_throw_is_strike?&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;score&lt;/span&gt;
        &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;..&lt;/span&gt;&lt;span class="number"&gt;10&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;inject&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;score&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;score&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="ident"&gt;score_for&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;score_for&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;
        &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;strike_score_for&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;is_strike_at?&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;
        &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;spare_score_for&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;is_spare_at?&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;
        &lt;span class="ident"&gt;open_score_for&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;first_throw_is_strike?&lt;/span&gt;
        &lt;span class="ident"&gt;is_first_throw_in_frame?&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="attribute"&gt;@rolls&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;last&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;is_first_throw_in_frame?&lt;/span&gt;
        &lt;span class="attribute"&gt;@rolls&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;odd?&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;open_score_for&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;
        &lt;span class="ident"&gt;first_throw_for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;second_throw_for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;);&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;spare_score_for&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;
        &lt;span class="ident"&gt;open_score_for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;first_throw_for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;next_frame&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;strike_score_for&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;
        &lt;span class="ident"&gt;score&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;open_score_for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;open_score_for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;next_frame&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
        &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;is_strike_at?&lt;/span&gt; &lt;span class="ident"&gt;next_frame&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
            &lt;span class="ident"&gt;score&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="ident"&gt;first_throw_for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;next_frame&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;next_frame&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)))&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
        &lt;span class="ident"&gt;score&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;next_frame&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;
        &lt;span class="ident"&gt;frame&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;is_spare_at?&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;
        &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;open_score_for&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="ident"&gt;is_strike_at?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;is_strike_at?&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;
        &lt;span class="ident"&gt;first_throw_for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;first_throw_for&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;
        &lt;span class="ident"&gt;score_at_throw&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;index_for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;second_throw_for&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;
        &lt;span class="ident"&gt;score_at_throw&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;index_for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;index_for&lt;/span&gt; &lt;span class="ident"&gt;frame&lt;/span&gt;
        &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="number"&gt;2&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;score_at_throw&lt;/span&gt; &lt;span class="ident"&gt;index&lt;/span&gt;
        &lt;span class="attribute"&gt;@rolls&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="punct"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;index&lt;/span&gt; &lt;span class="punct"&gt;?&lt;/span&gt; &lt;span class="attribute"&gt;@rolls&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 01 Oct 2009 13:37:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:5144dc80-1acc-4f58-9c87-60971b35354b</guid>
      <author>Brett Schuchert</author>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby</link>
      <category>Schuchert's Scattered Synapses </category>
      <category>Ruby</category>
      <category>bowling</category>
      <category>kata</category>
      <category>RSpec</category>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by cheap vps</title>
      <description>&lt;p&gt;I have not really used Ruby much. I&#8217;ve written a few tutorials, messed around with RSpec and Test::Unit and even Rails a bit, but I really don&#8217;t know Ruby that well. I get Ruby (the MOP, instances, blocks, open classes, ...) but there&#8217;s a difference between understanding that stuff and using it day-to-day.&lt;/p&gt;


	&lt;p&gt;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&#8217;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&#8217;ve also seen people surprised by how bob stores his scores, so in a sense it violates the law of least astonishment.&lt;/p&gt;


	&lt;p&gt;That&#8217;s neither here nor there, I got it working just fine &#8211; though handling strikes was a bit more difficult because I decided to store two rolls instead of one (so clearly, there&#8217;s no best answer, just ones that suck for different reasons).&lt;/p&gt;


	&lt;p&gt;After my first go around, I had a single spec with examples all under a single describe (what&#8217;s that term they&#8217;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.&lt;/p&gt;


	&lt;p&gt;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&#8217;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.
&lt;a href="http://www.turbovps.com/" rel="nofollow"&gt;cheap VPS&lt;/a&gt;
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.&lt;/p&gt;</description>
      <pubDate>Sun, 15 Aug 2010 09:52:27 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:732318af-d257-4869-9b95-b336dbb09ae9</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-20049</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by pass4sure dumps</title>
      <description>&lt;p&gt;Thanks for sharing.&lt;/p&gt;</description>
      <pubDate>Tue, 10 Aug 2010 05:21:11 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:558a2579-d6b4-49b0-8de9-af3cfd0a4ff6</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-19394</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by pass4sure</title>
      <description>&lt;p&gt;Nice post.&lt;/p&gt;</description>
      <pubDate>Tue, 10 Aug 2010 05:20:18 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:a76af281-a133-4609-8758-a8e35fedf500</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-19392</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by Games Collection</title>
      <description>&lt;p&gt;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&#8217;t like that basis all over the place, so I approved to abolish it by re-factoring.&lt;/p&gt;</description>
      <pubDate>Mon, 19 Jul 2010 01:11:13 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:b5dee599-7f1e-4e7c-8beb-57107cacbaf2</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-16693</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by Game Fair</title>
      <description>&lt;p&gt;The access was actual c-esque. I didn&#8217;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.&lt;/p&gt;</description>
      <pubDate>Fri, 18 Jun 2010 01:59:37 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:66aa5f58-7553-482e-8f48-9ce82f1b08a1</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-13183</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by Games</title>
      <description>&lt;p&gt;Works great&lt;/p&gt;</description>
      <pubDate>Thu, 03 Jun 2010 09:43:27 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:f4758697-3573-458c-b648-0100ef0d230e</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-12428</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by Games</title>
      <description>&lt;p&gt;It works great. Thanks&lt;/p&gt;</description>
      <pubDate>Thu, 03 Jun 2010 09:42:27 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:f325f77c-4f66-4236-b69b-132ef42d61f9</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-12427</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by Brett L. Schuchert</title>
      <description>Whew! That took a bit more than I expected. First, there was another error in one of the examples:
&lt;pre&gt;&lt;code&gt;      it 'should score game with single strike correctly' do
            roll 10
            roll 5
            roll 2
            roll_many 17, 0
            score_should_be 24
        end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Rolled one too many (17&amp;#8212;&amp;gt; 16). Makes sense I supose.&lt;/p&gt;


Next, I added several more negative examples than expected:
&lt;pre&gt;&lt;code&gt;    describe '10th frame number of rolls allowed' do
        before(:each) do
            roll_many 18,0
        end

        it 'should fail with open 10th and additional roll' do
            roll_many 2, 0
            lambda { roll 0 }.should raise_error(IndexError)
        end

        it 'should fail with spare 10th frame and 2 additional rolls' do
            roll_many 2, 5
            roll 5
            lambda { roll 0 }.should raise_error(IndexError)
        end

        it 'should fail with strike, spare and 1 additional roll' do
            roll 10
            roll_many 2, 5
            lambda { roll 0 }.should raise_error(IndexError)
        end

        it 'should fail with strike, strike and 2 additional rolls' do
            roll 10
            roll 10
            roll 5
            lambda { roll 0 }.should raise_error(IndexError)
        end
    end

    describe 'Too many pins in a frame' do
        it 'should not allow more than 10 on a single roll' do
            lambda { roll 11 }.should raise_error(ArgumentError)
        end

        it 'should not allow more than 10 in two rolls' do
            roll 6
            lambda { roll 5 }.should raise_error(ArgumentError)
        end
    end&lt;/code&gt;&lt;/pre&gt;

Ultimately, I ended up with a bit of changed code (and one ugly method:
&lt;pre&gt;&lt;code&gt;    def roll value
        verify value
        record value
    end

    def verify value
        raise IndexError, 'Too many rolls in game' if !should_allow_roll?
        raise ArgumentError, 'Too many pins rolled' if too_many_pins? value
    end

    def record value
        @rolls &amp;lt;&amp;lt; value
        @rolls &amp;lt;&amp;lt; 0 if first_throw_is_strike?
    end

    def too_many_pins? value
        (open_score_for current_frame) + value &amp;gt; 10
    end

    def current_frame
        (@rolls.length / 2) + 1
    end

    def should_allow_roll?
        max = 20
        max = 21 if is_spare_at? 10
        max = 22 if is_strike_at? 10
        max = 23 if is_strike_at? 11
        @rolls.length &amp;lt; max
    end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;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.&lt;/p&gt;


	&lt;p&gt;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&amp;#8217;s solution and add in the same negative examples and see how well it grows.&lt;/p&gt;


Here is the full source of the results:
&lt;p&gt;&lt;/p&gt;
&lt;b&gt;&lt;i&gt;bowling_score_card_spec.rb&lt;/i&gt;&lt;/b&gt;
&lt;pre&gt;&lt;code&gt;require 'spec_helper'
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 16, 0
            score_should_be 24
        end

        it 'should score a dutch-200, spare-strike, correclty' do
            5.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
            5.times do
                roll 10
                roll_many 2, 5
            end
            roll 10
            score_should_be 200
        end

        it &amp;quot;should score all 5's game as 150&amp;quot; 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

    describe '10th frame number of rolls allowed' do
        before(:each) do
            roll_many 18,0
        end

        it 'should fail with open 10th and additional roll' do
            roll_many 2, 0
            lambda { roll 0 }.should raise_error(IndexError)
        end

        it 'should fail with spare 10th frame and 2 additional rolls' do
            roll_many 2, 5
            roll 5
            lambda { roll 0 }.should raise_error(IndexError)
        end

        it 'should fail with strike, spare and 1 additional roll' do
            roll 10
            roll_many 2, 5
            lambda { roll 0 }.should raise_error(IndexError)
        end

        it 'should fail with strike, strike and 2 additional rolls' do
            roll 10
            roll 10
            roll 5
            lambda { roll 0 }.should raise_error(IndexError)
        end
    end

    describe 'Too many pins in a frame' do
        it 'should not allow more than 10 on a single roll' do
            lambda { roll 11 }.should raise_error(ArgumentError)
        end

        it 'should not allow more than 10 in two rolls' do
            roll 6
            lambda { roll 5 }.should raise_error(ArgumentError)
        end
    end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;&lt;b&gt;&lt;i&gt;bowling_score_card.rb&lt;/i&gt;&lt;/b&gt;
&lt;pre&gt;&lt;code&gt;class BowlingScoreCard
    def initialize
        @rolls = []
    end

    def roll value
        verify value
        record value
    end

    def verify value
        raise IndexError, 'Too many rolls in game' if !should_allow_roll?
        raise ArgumentError, 'Too many pins rolled' if too_many_pins? value
    end

    def record value
        @rolls &amp;lt;&amp;lt; value
        @rolls &amp;lt;&amp;lt; 0 if first_throw_is_strike?
    end

    def too_many_pins? value
        (open_score_for current_frame) + value &amp;gt; 10
    end

    def current_frame
        (@rolls.length / 2) + 1
    end

    def should_allow_roll?
        max = 20
        max = 21 if is_spare_at? 10
        max = 22 if is_strike_at? 10
        max = 23 if is_strike_at? 11
        @rolls.length &amp;lt; max
    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? &amp;amp;&amp;amp; @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_open_at? frame
        (open_score_for frame) &amp;lt; 10
    end

    def is_spare_at? frame
        (open_score_for frame) == 10 &amp;amp;&amp;amp; is_strike_at?(frame) == false
    end

    def is_strike_at? frame
        first_throw_for(frame) == 10
    end

    def index_for frame
        (frame - 1) * 2
    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 score_at_throw index
        @rolls.length &amp;gt; index ? @rolls[index] : 0
    end
end&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;


And finally, here&amp;#8217;s the output from running spec at the command line (minus the coloring):
&lt;pre&gt;
BowlingScoreCard
- should score 0

BowlingScoreCard Scores for Complete Games
- should score 0 for an all gutter game
- should show 20 for an all 1 game
- should score game with single spare correctly
- should score game with single strike correctly
- should score a dutch-200, spare-strike, correclty
- should score a dutch-200, strike-spare, correctly
- should score all 5's game as 150
- should score a perfect game correctly
- should not count a 0, 10 roll as a strike

BowlingScoreCard Scoring for open games
- should score just an open frame
- should score just a spare
- should score partial game with spare and following frame only
- should score an opening turkey correctly

BowlingScoreCard Scoring open game starting with a srike
- should score partial game with only strike
- should score partial game with strike and half-open frame
- should score partial game with strike and open frame
- should score partial game with strike and spare

BowlingScoreCard Open game starting with two Strikes
- should have a score of 30
- should score correctly with following non-mark
- should score correclty with third frame open

BowlingScoreCard 10th frame number of rolls allowed
- should fail with open 10th and additional roll
- should fail with spare 10th frame and 2 additional rolls
- should fail with strike, spare and 1 additional roll
- should fail with strike, strike and 2 additional rolls

BowlingScoreCard Too many pins in a frame
- should not allow more than 10 on a single roll
- should not allow more than 10 in two rolls

Finished in 0.125306 seconds

27 examples, 0 failures
&lt;/pre&gt;</description>
      <pubDate>Mon, 05 Oct 2009 10:37:47 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:757ec97c-fa77-4027-bf70-3b9ad1244a83</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-4379</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by Brett L. Schuchert</title>
      <description>&lt;p&gt;&lt;b&gt;&lt;i&gt;Philip Schwarz&lt;/i&gt;&lt;/b&gt; wrote:
&lt;blockquote&gt;...two dutch-200 ones, which I need to investigate, possibly in the light of what&amp;#8230;&lt;/blockquote&gt;
 Yep, as David mentioned, the examples are wrong. See post just above this one.
&lt;p&gt;&lt;/p&gt;
And cool seeing &lt;a href="http://www.easyb.org/" rel="nofollow"&gt;easyb&lt;/a&gt;. Thanks for showing us that.&lt;/p&gt;</description>
      <pubDate>Mon, 05 Oct 2009 06:58:53 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:9a7dfa35-79ed-45ad-b4e6-db76a0b5aa1a</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-4378</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by Brett L. Schuchert</title>
      <description>&lt;p&gt;&lt;a href="http://notetoself.vrensk.com/" rel="nofollow"&gt;David Vrensk&lt;/a&gt; wrote:
&lt;blockquote&gt;Brett, I&#8217;m confused by the example &amp;#8230;&lt;/blockquote&gt;&lt;/p&gt;


Do&amp;#8217;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):
&lt;pre&gt;
  def score
        (1..10).inject(0){|score,frame|score+=score_for frame}
    end
&lt;/pre&gt;

	&lt;p&gt;I only score 10 frames, so the extra &amp;#8220;crap&amp;#8221; is ignored. In both of my dutch-200 games I should have 5.times &amp;#8230;, not 10.&lt;/p&gt;


I had not yet added negative cases:
	&lt;ul&gt;
	&lt;li&gt;Rolling over 10&lt;/li&gt;
		&lt;li&gt;Rolling over 10 in a single frame&lt;/li&gt;
		&lt;li&gt;Rolling too many frames&lt;/li&gt;
		&lt;li&gt;...&lt;/li&gt;
	&lt;/ul&gt;


&lt;p&gt;&lt;/p&gt;
If I had added those (and I thought about it but didn&amp;#8217;t do it), I would have caught those errors and never posted the 10.times.&lt;p /&gt;

	&lt;p&gt;I&amp;#8217;ll leave the errors in the blog, but I&amp;#8217;ll fix my code by adding code to validate the input, those tests will fail, then I&amp;#8217;ll fix the tests.&lt;/p&gt;


	&lt;p&gt;Great example of why having a navigator is good.&lt;/p&gt;</description>
      <pubDate>Mon, 05 Oct 2009 06:54:14 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:f864cb14-05b9-4347-abfc-544276074bcc</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-4377</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by Philip Schwarz</title>
      <description>&lt;p&gt;@Brett,&lt;/p&gt;


	&lt;p&gt;thanks to your post I finally got round to trying a BDD tool.&lt;/p&gt;


	&lt;p&gt;I took your specification, turned &lt;b&gt;Ruby&lt;/b&gt; into &lt;b&gt;Groovy&lt;/b&gt;, trivially turned &lt;b&gt;RSpec&lt;/b&gt; syntax into &lt;b&gt;&lt;a href="http://www.easyb.org/" rel="nofollow"&gt;easyb&lt;/a&gt; &lt;/b&gt;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.&lt;/p&gt;


	&lt;p&gt;Here is the translated specification:&lt;/p&gt;


&lt;pre&gt;
def roll(int pins){ game.roll(pins) } 
def roll_many(int pins, int rolls){ rolls.times{ game.roll(pins) } }
def score_should_be(int score) { game.score().shouldBe(score) }

before "Scores for Complete Games", { game = new Game() }

it "should score 0 for an all gutter game",
{
    roll_many(0,20)
    score_should_be 0
}

it "should show 20 for an all 1 game",
{
    roll_many(1,20)
    score_should_be 20
}

it "should score game with single spare correctly",
{
    roll_many(5,3)
    roll_many(0,17)
    score_should_be 20
}

it "should score game with single strike correctly",
{
    roll 10
    roll 5
    roll 2
    roll_many(0, 17) 
    score_should_be 24   
}

it "should score a dutch-200, spare-strike, correctly",
{
    [1..10].each{
      roll_many(5, 2)
      roll 10
    }
    roll_many(5, 2)
    score_should_be 200
}

it "should score a dutch-200, strike-spare, correctly",
{
  [1..10].each
  {
    roll 10
    roll_many(5,2)
  }
  roll 10
  score_should_be 200
}

it "should score all 5's game as 150",
{
  roll_many(5,21)
  score_should_be 150
}

it "should score a perfect game correctly",
{
  roll_many(10,12)
  score_should_be 300
}

it "should not count a 0, 10 roll as a strike",
{
  roll 0
  roll 10
  roll_many(1,18)
  score_should_be 29
 }

before "Scoring for open games", { game = new Game() }

it "should score just an open frame",
{
  roll 4
  roll 3
  score_should_be 7
}

it "should score just a spare",
{
  roll_many(5,2)
  score_should_be 10
}

it "should score partial game with spare and following frame only",
{
  roll_many(5,3)
  score_should_be 20
}

it "should score an opening turkey correctly", 
{
  roll_many(10,3)
  score_should_be 60
}

before "Scoring open game starting with a strike",
{
  game = new Game()
  roll 10
}

it "should score partial game with only strike",
{
  score_should_be 10
}

it "should score partial game with strike and half-open frame", 
{
  roll 4
  score_should_be 18
}

it "should score partial game with strike and open frame",
{
  roll 3
  roll 6
  score_should_be 28
}

it "should score partial game with strike and spare",
{ 
  roll 3
  roll 7
  score_should_be 30
}      

before "Open game starting with two Strikes",
{
  game = new Game()
  roll 10
  roll 10
}

it "should have a score of 30",
{
  score_should_be 30  
}

it "should score correctly with following non-mark",
{
  roll 4
  score_should_be 42
}

it "should score correclty with third frame open",
{
  roll 4
  roll 3
  score_should_be 48  
}
&lt;/pre&gt;</description>
      <pubDate>Sun, 04 Oct 2009 19:11:27 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:0d1392e6-bdb4-4454-92f9-2157e368079c</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-4343</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by David Vrensk</title>
      <description>&lt;p&gt;Brett, I&amp;#8217;m confused by the example &amp;#8220;it should score a dutch-200, strike-spare, correctly&amp;#8221;.  It looks like you&amp;#8217;re rolling 31 times (10*(2+1)+1).  I&amp;#8217;m not a bowler, but it looks to me like you are playing 21 frames which surely must be too much?&lt;/p&gt;


	&lt;p&gt;Regarding the use of the word &amp;#8220;kata&amp;#8221;, 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&amp;#8217;d superimpose two video recordings of a master performing a kata on two different days, you&amp;#8217;d never know that there were two recordings.  If we did a programming kata the same way, we&amp;#8217;d strive to end up with the exact same code written in the exact same order and pace.  I don&amp;#8217;t think that would be useful (but I&amp;#8217;m willing to be proven wrong).&lt;/p&gt;


	&lt;p&gt;Instead, the programming kata (in my mind) borrows the purpose and confinements (if that&amp;#8217;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.&lt;/p&gt;</description>
      <pubDate>Sun, 04 Oct 2009 08:27:26 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:86106df8-4988-479b-8686-811214573eee</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-4341</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by Brett L. Schuchert</title>
      <description>&lt;p&gt;Thanks David, too damn obvious for my knuckle head!&lt;/p&gt;


	&lt;p&gt;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&amp;#8217;ve picked up from the bdd community (in this example, only a few).&lt;/p&gt;


	&lt;p&gt;That I did not go with the same solution, I think, is good.&lt;/p&gt;


	&lt;p&gt;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.&lt;/p&gt;


	&lt;p&gt;Kata is defined as &amp;#8220;choreographed patterns of movements practiced either solo&amp;#8230;&amp;#8221; (according to wikipedia). Given that, I did use the bowling game example to practice using RSpec. I&amp;#8217;ve done the bowling kata as bob does it in Java (and C# and I think I might have done it once in C++).&lt;/p&gt;


	&lt;p&gt;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?&lt;/p&gt;


	&lt;p&gt;I see your take on the word. I don&amp;#8217;t hold the same definition. It&amp;#8217;s quite possible my definition is wrong, but I&amp;#8217;m going to stick to it until I&amp;#8217;m convinced otherwise. FWIW, I&amp;#8217;ve practiced forms in martial arts. In that case, the sequence of steps was the practice. So I grok the idea, I&amp;#8217;m just not sure how direct I want to interpret the metaphor.&lt;/p&gt;</description>
      <pubDate>Thu, 01 Oct 2009 16:45:53 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:fed9cdb4-595a-4a19-ab1f-22a4fbaf2a53</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-4334</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by GBGames</title>
      <description>&lt;p&gt;I don&amp;#8217;t know Ruby, and therefore, RSpec, but now I know what the &amp;#8220;it&amp;#8221; keyword is. B-)&lt;/p&gt;


	&lt;p&gt;My only concern is that the word &amp;#8220;kata&amp;#8221; is used when there is no form being followed. Uncle Bob&amp;#8217;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&amp;#8217;s no longer a kata, right?&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s an exercise. It&amp;#8217;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&amp;#8217;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?&lt;/p&gt;</description>
      <pubDate>Thu, 01 Oct 2009 15:10:36 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:246c471b-09b1-46df-b44e-d1ad57cccabc</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-4332</link>
    </item>
    <item>
      <title>"Bowling Game Kata in Ruby" by David Chelimsky</title>
      <description>&lt;p&gt;describe &amp;#8220;something&amp;#8221; {}
=&amp;gt; ExampleGroup&lt;/p&gt;</description>
      <pubDate>Thu, 01 Oct 2009 14:50:40 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:7dc2eb64-22e3-4289-a3b9-2b341ed5aca4</guid>
      <link>http://blog.objectmentor.com/articles/2009/10/01/bowling-game-kata-in-ruby#comment-4331</link>
    </item>
  </channel>
</rss>
