PR

開発に手詰まりを感じたら静的設計を見直そう

2015年1月28日(水)
吉谷 愛
  1. [高梨]さすがですね! それではいよいよ今回のメインテーマにうつりましょう。このまま進めると連載第1回目の繰り返しになってしまう、ではどうすればいいか? まずは今から行うことをまとめました。当たり前のことしか書いていませんが。
フレームの得点計算について検討する

図12:フレームの得点計算について検討する(クリックで拡大)

  1. [古谷]そうですね。当たり前のことしか書いてない…。
  2. [高梨]TDDを進めていると、今回のように「手詰まり感」が出てくることがあります。そのタイミングで、一度静的な設計を見直しましょう。それでは次の図13を見てください。上段が、今まで古谷さんがTDDを遂行する過程で実装したBowlingGameクラスです。
静的設計のブレイクスルー

図13:静的設計のブレイクスルー(クリックで拡大)

  1. [古谷]うーん、こうして見ると今のBowlingGameクラスって、いろんな機能や属性が追加されてブクブクになっていますね…。
  2. [高梨]いえ、決してそんなことはありません。ただフレーム毎の得点を取得するという「新たな要求」に答えるためには「振る舞い」や「事前条件・事後条件」等の動的設計だけでなく、静的設計である「インターフェース」や「名前(ネーミング)」も、一歩前進させる必要があります。
  3. [古谷]あれ? すみません、あまりRubyに詳しくないので勘違いかもしれませんが、RubyはJavaと違ってインターフェースって存在しないのでは……?
  4. [高梨]その通り、RubyにはJavaでいうところのインターフェースは存在しません。ここでいう「インターフェース」は言語仕様のことではなく、もう少し広義の意味です。
    さて図13の下段は、フレーム毎に得点を取得するためのFrameクラスを新しく設計したものです。現段階ではまだこのクラスの最終形は見えていませんが、先々迷わないように、方針は決めておきます。この図の中の「基本的な方針」がそれにあたります。ざっくり言うとFrameクラスは会社組織で例えて言えば現場職、BowlingGameクラスは管理職といったところでしょうか。
  5. [古谷]基本的に直接Frameからではなく、BowlingGame経由で値を取得するのですね。
  6. [高梨] そうです。私が先程から言っている「インターフェース」とは、まさにそういう意味の「インターフェース」です。それでは次の図14をご覧ください。TDDを行う際には、このように「動的設計」と「静的設計」を交互に行き来することで、全体的な設計を洗練していきます。
動的設計と静的設計を行き来することで、洗練していく

図14:動的設計と静的設計を行き来することで、洗練していく(クリックで拡大)

  1. [古谷]えーと、先輩が言わんとしていることはなんとなくわかりました。ですが、今、自分が何から手をつけるべきなのかわかりません(泣)。
  2. [高梨]大丈夫です。ちゃんとインクリメンタルに行きますので安心してください。
    まずは先程提示したFrameクラスのテストクラスを用意しましょう。テストケースは、今まで通り「フレームの第1投球も第2投球もゼロ(ガター)の時」からはじめましょう。メソッド名は、私が先程提示したFrameクラスのクラス図を参考にしてください。そのあとで、Frameクラスにそのメソッドを実装します。これも最初は無条件でゼロを返す形で大丈夫です。
  3. [古谷]あ、それなら大丈夫です…… はい、通りました!
Frameクラスの最初の実装

図15:Frameクラスの最初の実装(クリックで拡大)

  1. [高梨]素晴らしい! では次に、必要最小限の点数計算を実装しましょう。全ての投球で1ピンだけ倒した場合のテストケースを記述してエラーを確認した後、Frameクラスにメソッドを実行してテストケースを通すところまでお願いします。
最小限の点数計算を実装する

図16:最小限の点数計算を実装する(クリックで拡大)

  1. [古谷]はーい! これで良いですか?
  2. [高梨]大丈夫です! それでは、FrameクラスをBowlingGameクラスに組み込んでください。
  3. [古谷]えっつ!? い、いきなりですか?
  4. [高梨]はい。まずはBowlingGameTestクラスに「全ての投球がガターの場合の第1フレームの得点」テストケースを追加してください。エラーを確認したら、下記ロジックの追加で今回定義したテストは通るはずです。とりあえずここまでで大丈夫です。インクリメンタルに行きましょう。
  1. BowlingGameクラスにフレームを格納する変数(最初は配列でなくてOK)を定義
  2. BowlingGameクラスにフレームに投球を記録するロジックを追加
  3. BowlingGameクラスのframe_scoreメソッドの修正
  1. [古谷]あ、それだけなら多分大丈夫です。これでどうでしょう?
FrameクラスをBowlingクラスに組み込む

図17:FrameクラスをBowlingクラスに組み込む(クリックで拡大)

  1. [高梨]大丈夫です! 素晴らしい、いやいや古谷さん、最初から比べると見違えるようになりましたね!
  2. [古谷]ありがとうございます。ですが、今から他の部分の組み込みを進めていくわけですが、何から手をつけて良いのか、実はまだよく把握できていません………。
  3. [高梨]それでは、まずはBowlingGameクラスとFrameクラスの役割をはっきりさせましょう。こちらの図18を見てください。今までBowlingGameでまかなってきた作業のうち、以下のものについてはFrameクラスが行うようにします。
  • 投球の記録
  • フレーム完了判定
  • 投球結果判定(スペアかストライクか等)
  • ボーナスの保持
  • 記録した点数を返す
  1. [高梨]一方BowlingGameクラスは、Frameを適切に管理・制御する役目を担当することにします。ちなみに太字が一応実装したもの、下線が次回対応予定のものです。
FrameとBowlingGameクラスの役割を分担する

図18:FrameとBowlingGameクラスの役割を分担する(クリックで拡大)

  1. [古谷]こんな風に書かれているとできそうな気がします! でも、今回は先輩が書いてくださったので大丈夫なのですが、自力では私にはまだ難しい気がします…。
  2. [高梨]こういう場合は「MECE」と言われるロジカルシンキング手法を使うと効果的です。MECEは“Mutually Exclusive and Collectively Exhaustive”の略語で、簡単にいうと「重複なく、漏れなく」という意味です。BowlingGameクラスとFrameクラスの役割が重複していないか、漏れていないかという視点で、今までの設計を俯瞰します。ここでいきなり最終形をつくりあげようとせず、現時点で明確になっている機能(ブレイクスルー前のBowlingGameクラスがもっていた機能)だけに着目して大丈夫です。後々新しい役割が出てきたら、「管理職はBowlingGame」「現場職はFrame」という最初の基本方針に沿って責務を分担して行きます。

    ん? どうしました? 顔色があまり良くないようですが、不安になりましたか?
  3. [古谷]は、はい…… 。連載3、4回目までは楽勝だったのですが、今回になって難易度が跳ね上がった気がします。一瞬でも「TDDに関してはほぼ理解できた気がする」と言った自分を殴りたいくらいです。ホント、勉強すればするほどわからないことがどんどん出てきますね。はあ……
  4. [高梨]まあまあ。今から僕が話すことは古谷さんのため息の回答になっていないかもしれませんが、良かったら参考にしてください。僕は勉強をする過程で出てきた疑問点を「わからないこと」ではなく「知りたいこと」ととらえるようにしています。「わからないことがどんどん増えていく」と考えると辛いですが、「知りたいことが増えている→興味の幅が広がっている」と捉えると学習意欲が萎えませんよ。そしてやっぱり事実として、勉強すれば確実にわかることは増えていきます。実際、第1回の時の古谷さんと今の古谷さんは別人のようです。大丈夫です、自信を持ってください。TDDはテストと実装をインクリメンタルに進めることで、プログラマが自信を獲得する開発手法です。次回、BowlingGameクラスとFrameクラスの「責務の分担」の実装を進めることで、今の不安を自信に変えて行きましょう!
  5. [古谷]あの高梨先輩がここまで励ましてくれるなんて…は、はい、頑張ります!
フロイデ株式会社 代表取締役

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

連載バックナンバー

Think IT会員サービス無料登録受付中

Think ITでは、より付加価値の高いコンテンツを会員サービスとして提供しています。会員登録を済ませてThink ITのWebサイトにログインすることでさまざまな限定特典を入手できるようになります。

Think IT会員サービスの概要とメリットをチェック

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