ボウリングでストライクを取得した場合のテストケースを考える

2014年11月19日(水)
吉谷 愛

図6: TDDの流れ(クリックで拡大)

  1. [古谷] この図、第1回目の連載でも見せてもらいましたが、今見ると全然印象が違いますね。実感があるというか。
  2. [高梨] それは、古谷さんの成長の証拠だと思いますよ。ではリファクタリングに入りましょう。まず、スペアの判定と計算を行っている部分を、別メソッドにしましょう。別メソッドにしたら、その時点でテストも行ってください。といっても、テストメソッドを実行するだけで大丈夫です。
  3. [古谷] はい! メソッド名はどうしましょうか?
  4. [高梨] そうですね、判定だけでなく、スペアのボーナス計算も行っていますから、calc_spare_bonusなんてどうでしょう?
  5. [古谷] はい、こんな感じですか?

図7: スペアのボーナス計算メソッドの抽出(クリックで拡大)

  1. [高梨] 大丈夫です!では同じ要領で、ストライクの判定とボーナス計算を行うメソッドの定義をしてください。テストも忘れずにお願いします。
  2. [古谷] はい!これでどうでしょう?

図8: ストライクのボーナス計算メソッドの抽出(クリックで拡大)

  1. [高梨] 素晴らしいです! ではついでに、投球がフレームの2投目かどうか判断させる部分も別メソッドにしましょうか? メソッド名はproceed_next_shotなんてどうでしょう?
  2. [古谷] はい!こんな感じですか?

図9: フレーム投数の更新メソッドを抽出(クリックで拡大)

  1. [高梨] 大丈夫です、それにしても、だいぶ慣れてきましたね。
  2. [古谷] はい、かなり楽しくなってきました♪
  3. [高梨] では、この勢いのまま「連続ストライク」に進みましょう。古谷さん、下記のような投球をした場合、スコアは何点になりますか?
  • 第1投目:10ピン倒す(ストライク)
  • 第2投目:10ピン倒す(ストライク)
  • 第3投目:3ピン倒す
  • 第4投目:1ピン倒す
  • 残り14投球:すべてガタ—
  1. [古谷] えー……。
  2. [高梨] 難しく考える必要はありません。直後の2投球がボーナスになるので、最初のストライクのボーナスが10+3、次のストライクのボーナスが3+1になります。倒したピン数の合計は24なので、ボーナスとあわせて、41になります。それでは、連続ストライクのテストを実装後、実行してください。
  3. [古谷] はい…… あ、うまくいきません……。

図10: 連続ストライク(ダブル)のテストケース(クリックで拡大)

  1. [高梨] 大丈夫です。では、ここからまた一緒に考えていきましょう。前回同様、目の前の問題を引き起こしている原因を考えてみてください。
  2. [古谷] うわー、これホントさっぱりわからないですけど…… 3点足りませんよね、なぜでしょう?
  3. [高梨] おっ、いいところに気が付きましたね?
  4. [古谷] そうですか?
  5. [高梨] はい。なぜ3点足りないのでしょう? calc_strike_bonusメソッドを見直してみてください。
  6. [古谷] はい。えーと…… あっ、これじゃだめですよ!!
  7. [高梨] なぜでしょう?
  8. [古谷] だって、連続ストライクになったら、2回目のストライクのボーナスで、1回目のストライクのボーナスカウントがまだ1つ残っているのに上書きされています!
  9. [高梨] その通りです! その結果、第1フレームの残ボーナス回数がリセットされてしまうため、第1フレームのストライクのボーナスとなる、ストライク直後の第2投目が加算されなくなっているのです。

図11: 連続ストライクの残ボーナス回数の状態(クリックで拡大)

  1. [古谷] 難しかったけど、わかりました。
  2. [高梨] それではこの調子で、次の段階である「この問題の回避策」の検討へとすすみましょう。
  3. [古谷] ……すみません、連続ストライク用に残りボーナス回数を格納する変数をもう一つ持つ以外、思い付きません。
  4. [高梨] 大丈夫です! それでいきましょう。だいぶ難易度が高くなっていますが、古谷さんはほぼ自力で「目の前の問題を引き起こしている原因」と、「その回避策」を考え付いています。せっかくですから、このまま次の段階である「変更する際の手順」も、古谷さんが考えてみてください。
  5. [古谷] 変数をもうひとつ定義していいなら、こんな感じになります。
  1. @double_bonus_count変数を定義。初期値はゼロ。
  2. def calc_strike_bonus(pins)メソッド内のstrike_bonus_countの@scoreにボーナス追加ロジックの直後に下記ロジックを追加
    (ア)@double_bonus_countの値が1以上だったら@scoreに倒したピン数を追加して、@double_bonus_countの値を-1する。
  3. 倒したピン数が10だったら、ロジックを下記に修正
    (ア)@strike_bonus_countがゼロだったら2をセット
    (イ)@strike_bonus_countがゼロ以外なら、@double_bonus_countに2をセット。
  1. [高梨] いいですね! では実装してみてください。
  2. [古谷] はっ、はい!

図12: 残ボーナス回数を2種類持つことで問題を回避(クリックで拡大)

  1. [古谷] 動きました!!
  2. [高梨] 素晴らしいです! では、確認も含めて、ターキーのテストケースをお願いします。
  3. [古谷] たーきー? なんですかそれ?
  4. [高梨] ボウリングでは、3連続ストライクのことをターキーといいます。古谷さん、下記のような投球をした場合、ボウリングでは何点になりますか?
  • 第1投目:10ピン倒す(ストライク)
  • 第2投目:10ピン倒す(ストライク)
  • 第3投目:10ピン倒す(ストライク)
  • 第4投目:3ピン倒す
  • 第5投目:1ピン倒す
  • 残り12投球:すべてガタ—
  1. [古谷] えーと、第1投目のボーナスが10+10、2投目のボーナスが10+3、3投目のボーナスが3+1ですよね。で、通常の1投目から5投目の得点と合計して…… 71点でしょうか?
  2. [高梨] その通りです! では、ターキーのテストケースの実装と実行をお願いします。
  3. [古谷] えーと…こんな感じですか?

図13: 3連続ストライク(ターキー)のテストケース(クリックで拡大)

  1. [高梨] 問題なく動作しましたね♪
  2. [古谷] 良かった……。
  3. [高梨] それでは、このよい状態のまま、次回は復習をかねて「スペアとストライクの複合テストケース」を実装した後、フレーム単位で得点を取得するインターフェースの実装まで進みましょうか?
  4. [古谷] えっ? フレーム単位で? そうなったら最初から全部作りなおしじゃないですか!!
  5. [高梨] 今までは動的設計である「振る舞い」や「事前条件・事後条件」を中心に説明しましたが、次回は静的設計である「インターフェース」や「名前(ネーミング)」に言及していきます。
  6. [古谷] 難易度がいきなり上がったような気がするのですが、大丈夫でしょうか…?
  7. [高梨] 大丈夫です。次回もインクリメンタルに進めましょう。今の古谷さんなら大丈夫です。このプログラムと一緒に、古谷さん自身もブレイクスルーしましょう。
  8. [古谷] は、はい! 頑張ります!!
フロイデ株式会社 代表取締役

「最新のアーキテクチャを追及し続ける技術者集団」を目指す、フロイデ株式会社代表取締役社長。現在は、自身のCOBOLからRailsまでの非常に幅広い開発経験や、学生や未経験社員への技術指導経験を糧に、技術講師としてソフトウエアエンジニアの育成に注力している。2013年06月より、初心者向けの「はじめようRuby on Rails開発!」シリーズを考案。“技術者の立場にたった、技術者の心に火をつける”熱い講義をモットーとしている。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています