SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

C#で始めるテスト駆動開発入門

TDDBC大阪の課題をC#でやってみる ~ クラス設計とTDD

C#で始めるテスト駆動開発入門(5)

  • X ポスト
  • このエントリーをはてなブックマークに追加

クラス設計とTDD

 自動販売機クラスがひととおり完成しました。その全体は、クラス図で示すと次のようになりました。

自動販売機のクラス図

 冒頭で示した「飲み物自動販売機の概略」図が、ほぼそのままのイメージでモデル化できています。これはTDDBC大阪のお題が優れていたからであって、いつもこのように上手く行くとは限りません。それでも、最初におおまかなクラス設計を考えておくことは大切です。

 「TDDしていくなかでクラス構造が自然と作られていく」というようなことが言われますが、まったくのゼロから始めたのでは、気が遠くなるくらいの試行錯誤が必要になってしまうでしょう。実際の開発では、「TDDによってクラス設計を煮詰めていく」のが良いでしょう。事前にある程度までクラス設計を行なっておき、TDDしながら細部を詰めていく、また、クラス設計を手直ししていく、そういう感じです。

 TDDしながらクラス設計を詰めていくと、テストしやすい(テスタビリティの高い)クラス設計になるであろうとは予想できます。すなわち、クラスやメソッドの粒度は小さく、メソッド内の分岐の数は少なく、クラス間は疎結合になっていきます。参考までに、コードメトリックスの結果も載せておきます。

自動販売機のコードメトリックス

 なお、このコードメトリックス分析と前出のクラス図は、Visual Studio 2012 RCで作成しました。

TDDから見るクラス設計指針

 TDDしているときに手が止まったら、それはクラス設計を改善すべきサインなのかもしれません。最後に、これまで筆者が見てきた例をいくつか挙げておきます。

  • テストが書きにくい
    • 公開されているインターフェースからテスト対象が遠くてテストしにくいのかもしれません。その場合は、テスト対象をprivateからinternalに変えてしまいましょう。たとえば商品ラックが持っているビンのテストをするのに、自動販売機のインターフェースしか使えなかったとしたら、面倒なだけでなく、自動販売機にテストのためのインターフェースが増えることになってしまいます(しかも自動販売機としては本来は不要なインターフェースです)。
    • 他クラスへの依存性が高すぎるのかもしれません。疎結合なクラス構成にできないか、検討してみましょう。テスト対象のメソッド(またはその一部分)を、依存先のクラスや新設のクラスに移すことも検討しましょう。
    • 依存先のクラスがテストコードから制御しにくい場合は、インターフェースを定義してモックなどを使えるようにすべきかもしれません。
  • コードが書きにくい
    • テストは書けたけれどコードが書きにくいのは、テストが大きすぎるのかもしれません。テストの粒度を小さくする際に、クラスも分割した方が良いことに気付くことがあります。今回、「購入可能な商品リスト」は、商品ラックの在庫リストと、コインメックの預り金を別々にテストファーストしてから、最後にまとめ上げたメソッドを作りました。これらが全部同じクラスに入っていて、最後に作ったテストケースから始めたとしたら、どうなっていたでしょう。
  • テストの準備が長い
    • テスト対象のメソッドを呼び出す前の準備にたくさんのコードが必要な場合、オブジェクトの組み立てが上手く自動化できていないのかもしれません。適切な場所で組み立てていますか?自動販売機の例では、ビンを商品ラックに組み込むのは商品ラックの中でやっていますが、これを自動販売機クラスでやってしまうと、商品ラックをテストするだけのために自動販売機全体を組み立てる必要が出てきてしまいます。
    • テストデータの準備などで行数が掛かっているのであれば、メソッドに括り出します。
  • テストの結果判定が長い
    • ひとつのメソッドでたくさんの状態に変化が生じるのは、それが予測しにくい場合は使いにくいメソッドになります。それはクラス設計に起因しているかもしれません。
    • 結果を判定するために別のオブジェクトの状態を見ないといけないのであれば、そのメソッドの場所を考え直してみるとよいかもしれません。
    • オブジェクトの比較のために複数のプロパティをアサートしているのなら、オブジェクトを比較するメソッドを作った方が良いかもしれません。
    • 状態を判定するために複数のプロパティをアサートしている場合、じつはそれらは状態に依存しているだけの変数で、本当に知りたい状態が隠れているのかもしれません。
  • テストクラスが肥大化してきた
    • テスト対象のクラスごとにテストクラスを1つ作るという一般的なやり方の場合、これは製品クラスを分割すべきサインです。
  • アサート文が上手く書けない、不細工になる
    • 本当に必要としている情報を表現できていないのかもしれません。あるいは、ジュースクラスでEqualsメソッドのオーバーライドを作ったように、比較のためのメソッドが必要なのかもしれません。

まとめ

  • TDDBD大阪2.0の課題をC#でやってみた。クラス設計も同時に進めていくことになるという、良い課題であった。
  • TDDで自動的にクラス設計ができたりはしない(少なくとも現実的な時間では)。クラス設計を洗練し、詳細を詰めていく補助として、TDDは役立つ。また、TDDは、小粒度で疎結合、かつテスタビリティの高いクラス設計に向かわせるバイアスを与える。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
C#で始めるテスト駆動開発入門連載記事一覧

もっと読む

この記事の著者

biac(ばいあっく)

HONDA R&Dで自動車の設計をやっていた機械屋さんが、技術の進化スピードに魅かれてプログラマーに。以来30年ほど、より良いコードをどうやったら作れるか、模索の人生。わんくま同盟の勉強会(名古屋)で、よく喋ってたりする。2014/10~2019/6 Microsoft MVP (Windows Devel...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/6633 2012/06/29 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング