<< たくさんの書評、ありがとうございます | main |

新訳版『テスト駆動開発』に学ぶオブジェクト指向設計

---
---
コメント:和田卓人(t_wada)さんによる、名著の新訳版。


和田卓人(t-wada)さんによる新訳版『テスト駆動開発』が出版されました。


オブジェクト指向でソフトウェアを開発するのであれば、この本とマーチンファウラーの『リファクタリング』は必読書だと思います。古典ともいえる『テスト駆動開発』が和田さんの手によって新訳版として復刊されたことは、ほんとうにすばらしいことです。


この本が出版された経緯と、和田さんはじめ関係者の方々のご努力は、和田さんのブログから知ることができます。

新訳版『テスト駆動開発』が出ます


この新訳本は、単に原著が日本語で読めるようになっただけではありません。和田さんの手によって、原著では手に入れることができないすばらしい価値が手に入ります。


一つは、サンプルコードの工夫です。


  • できるだけ省略はしない
  • 変更箇所を目立つようにした
  • 各章末にその時点での全コードを記載する


これらの工夫により、本に書かれた内容が、より具体的に理解できるようになりました。また、実際に手を動かしてみるときに、迷子になりそうな個所が一掃されました。大勢の技術者にテスト駆動開発を伝える活動をされてきた和田さんの知見とノウハウ、思いが、このサンプルコードの工夫に結びついているのだと思います。


もう一つすばらしい内容が、付録Cとして追加された訳者の和田さん自身の解説「テスト駆動開発の現在」です。テスト駆動開発というムーブメントの歴史を振り返りつつ、現在の状況と、これからの展望が、わかりやすくまとめらています。

「テスト駆動開発の現在」で和田さんが書かれているように、いろいろな意味で状況が変わった現在こそ、もう一度、テスト駆動開発の本来の意味を考え、何が大事なことなのかを改めて理解して手に入れる好機です。新訳版『テスト駆動開発』は、和田さんのこの解説により、原著以上の今日的な新しい価値が与えられたと思います。


新訳版『テスト駆動開発』の内容を、オブジェクト指向の設計の考え方とやり方に焦点を合わせながら、簡単に紹介したいと思います。

本の帯にも書かれているように、「TDDはテスト技法ではない。分析技法であり、設計技法であり、開発のすべてのアクティビティを構造化する技法」です。


テスト駆動開発の2つのシンプルなルール


  • 自動化されたテストが失敗したときのみ、新しいコードを書く
  • 重複を除去する

(「まえがき」から)


一つ目のルールは、テスト駆動開発の基本として多くの人が理解し実践していると思います。しかし、2番目のルールはどうでしょうか? 「オブジェクト指向の設計」という観点からは、この2番目のルールが重要な意味を持ちます。

コードの重複を排除することで、コードを読みやすくし、変更があった時の影響範囲を狭い範囲に閉じ込めるのが、オブジェクト指向で設計する目的でありメリットです。

テスト駆動開発の基本サイクルはレッド・グリーン・リファクタリングです。リファクタリングを繰り返しながら「重複を除去する」活動こそTDDの本質です。


この本のサンプルを読み進めるときには、この2番目のルール「重複を除去する」ために、どのようなリファクタリングを行っていくかに注目してみてください。オブジェクト指向の設計で、どのようにコードの重複を除去するのかを、手を動かしながら体験できるのが、この本のすばらしい点です。


開発活動の目的と背景を理解する


ソフトウェア開発には、背景と目的があり、それぞれの置かれた状況があります。この本の最初のサンプルである「多国通貨」がなぜ必要になったのか、「多国通貨」にどのようなビジネス価値があり、変更の対象となるコードはどのような状況にあり、開発者たちのどのような経験を積み重ねてきているか。


そういう目的や背景が「はじめに」で説明されています。サンプルコードに飛び込む前に、この「はじめに」を熟読すべきです。ソフトウェア開発とは、こういう目的と背景の中で、積み重ねてきた経験や技術資産の延長として行うものです。TDDを取り入れるということは、こういう目的・背景・状況をよく理解することが前提です。


ビジネス価値は、技術者が直接コントロールはできません。しかし、スキルを身につけること、コードを整理し、テストを整備することは、技術者自身がコントロールできます。一朝一夕にできることではありませんが、日々の開発の中で、少しずつコードの整理とテストの整備を積み重ね、スキルを磨く活動を進めていくことがTDDの基本です。


ビューを使って仕様をざくっと理解する


第1章「仮実装」の冒頭で、レポート機能のサンプルが提示されています。レポートや画面のように、利用者が目にする情報(ビュー)は、要件を分析し、理解するためのわかりやすい手がかりです。

このレポートの出力例を元にして、何をすべきかをTODOとして書き出していく。これが「分析」活動です。


簡単な例ですが、TDDの考えるソフトウェア開発の基本の流れが明示されています。コードを書く人間が、利用者が使うレポートを参考にしながら、どのような仕様を満たすべきかを考える、ということです。


注意してほしいのは、ここには、仕様をヒアリングする、という活動が登場しないことです。それは、このチームが、このプロダクトの開発に何年もかかわってきて、この問題領域(ドメイン)について、かなりの知識を持っているという背景もあります。しかし、開発者にとっても「多国通貨」という領域は未知の領域だったはずです。

それにもかかわらず、開発者たちは仕様について、自ら考えながら、TODOリストを書きだしている、という開発スタイルが、TDDの基本です。開発者が仕様について自ら能動的に考えるのは、ドメイン駆動設計の根底にある考え方と共通です。開発者自身が何を作るべきかを考えるのは、オブジェクト指向開発の底流にある根本思想です。


モジュール化の方針


プログラム単位をどのように分割し、どのように組み立てるかは、手続き型プログラミングとオブジェクト指向プログラミングのもっとも大きな違いです。

要求仕様はレポート機能の分析から開始しています。しかし、書こうとしているプログラムの単位は、「レポート機能」とか「レポートサービス」ではありません。レートを換算するための RateConverterクラスとか、ReteConversionService を書こうとはしていません。


そうではなく、最初に登場するのは、Dollar.java つまり Dollar クラスです。


「換算する」という機能に注目するのではなく、換算するためには、DollarクラスとCHF(スイスフラン)クラスという単位でプログラムを書こうという発想です。


これは、ソフトウェア全体の構造設計の大きな基本方針の違いです。


「換算する」という機能に注目して、それをそのままプログラミングの単位として手続き(サブルーチン)に分解しようというのが、典型的な手続き型のアプローチです。データを持つクラスと処理を持つクラスを分け、トランザクションスクリプトを開発するスタイルです。


それに対し、ドルやスイスフランという関心事の単位にプログラムを分割する発想が、典型的なオブジェクト指向のスタイルです。

まず、何を対象にしているのかに注目します。最初の段階では「換算」よりも、もっと基本的な部品である「ドル」や「スイスフラン」をどうオブジェクトとして表現するかからスタートしています。問題領域に登場する具体的な関心の対象をオブジェクトで表現してみる。典型的なドメインモデルの開発スタイルです。


手続きとしてトップダウンにプログラム単位を分割していくか、何を扱いたいかの具体的な対象に注目して、ボトムアップに部品を用意していくか。この二つのアプローチの違いは、ソフトウェアの設計方針の大きな分かれ道です。


『テスト駆動開発』では、当たり前のように、Dollar.java からスタートしています。第1章「仮実装」で、ここからスタートしていることは、ほんとうに味わい深いところです。

レポート機能とその出力サンプルを分析しながら、プログラミングのアプローチは、機能単位や出力のビュー単位の開発ではなく、問題領域の具体的な関心事「ドル」と「スイスフラン」をオブジェクトとして表現することから手を付けています。


最終的には換算機能を実現するわけですが、そこに近づくために、まず、ドルやスイスフランという基本的な部品から手をつけるという、このボトムアップのスタイルこそ、オブジェクト指向らしい設計スタイルです。


クラスの粒度、ユニットテストの単位


第1章「仮実装」から第16章「将来の読み手を考えたテスト」までは、レポート機能に多国通貨に対応するための部品となるオブジェクトを、発見し、成長させていく過程が具体的に描かれています。実施に手を動かしながら、その過程をぜひ体験してみてください。

特にTDDの2番目の基本ルール「重複を除去する」ためのリファクタリングに注目してください。まどろっこしいような手順を踏んでいる理由のいくつかは、この「重複を除去する」活動を例示するためだ、ということが体感できるはずです。


16章までの一連の開発プロセスと成果物の振り返りが、第17章「多国通貨全体ふりかえり」です。

この章で注目したいのは、136ページの「コードメトリクス」です。


クラス数


プロダクトコードのクラス数は5です。テストコードのクラス数は1です。

つまり、一つのユニットテストは、5つのクラスを対象にしています。5つのクラスは、moneyパッケージとしてまとめられています。テストの対象の「ユニット」は、個々のクラスではなく、moneyパッケージです。


このテストクラス数とプロダクションのクラス数の比率は、オブジェクト指向で設計する場合のおおまかな指針として参考になります。ひとかたまりのユニットとしてテストする内容は、5つくらいのクラスを組み合わせた処理になる、という比率です。一つのプロダクションクラスに一つのユニットテストというのは、おそらく、プロダクションのクラスの粒度が大きすぎます。

もっと関心事を小さなクラスに分けて、それを組合せる、というのがオブジェクト指向設計の基本です。また、パッケージが、テストの単位という点もパッケージ設計やテスト設計の指針になります。


第16章の章末に記載された次の5つのクラスへ分割する設計をぜひ味わってみてください。

  • Money.java
  • Sum.java
  • Expression.java
  • Bank.java
  • Pair.java


まだ、開発途中ということもありますが、いちばん大きなMoneyクラスでも100行未満です。通貨の組み合わせを表現するために、Pairという10行程度のクラスを導入しています。


こういう用途をより具体的にした小さなクラスを部品として用意する、というオブジェクト指向らしい設計スタイルを、この本を通じて体験することができます。いくつかのメトリクスを具体的に見てみます。


メソッドの行数


プロダクションコードでは、4.5行/メソッドです。メソッドの宣言と中括弧もカウントしていますから、実質的には、メソッドの中身は3行未満ということです。これは、開発途中だから、ということではありません。「重複を除去する」を徹底すると、自然に、こういう短いメソッドが増えるということです。


テストコードは、7.8行/メソッドです。これは、表の注釈にあるように、テストコードのほうは「重複したコードを除去しきれていない」からです。


TDDの2番目のルール「重複を除去する」をどの程度、実践できているかは、このメソッドあたりの行数から推測できます。


オブジェクト指向の設計で、コードの重複を除去する活動の結果は、メソッドの行数としてある程度は観測できるということです。


循環的複雑度


この尺度は、簡単に言えば、コードの中にif文の分岐が多いか少ないかの指標です。

テストコードは、1.0。つまり、if文(条件分岐)がまったくないということです。


そしてプロダクションコードでも、なんと、1.05です。プロダクションコードでもif文(条件分岐)がほとんど登場していない、ということです。


if文は、複雑さの根源です。オブジェクト指向で設計するということは、この複雑さを取り除くことも重要な目標です。サンプルコードを読みながら、どのように、条件分岐の複雑さを除去していっているかをぜひ手を動かしながら味わってみてください。途中で「継承」が登場します。しかし、重複を徹底的に除去していく過程で、最終的には、継承を取り除くリファクタリングを行います。継承はオブジェクト指向の強力な手段ですが、コードの重複を除去するためには、最善の手段とは限らないのです。継承を除去するというリファクタリングは、なかなか味わい深いものがあります。




『テスト駆動開発』の第一部の「多国通貨」の例について、オブジェクト指向設計という観点から、内容を簡単に紹介してみました。この本は、読み物というより、手を動かして体験学習をするための教材なんだと思います。ぜひ、実際にコードを書きながら、コードの変化していく様子と、なぜ、そうするのか、何が変わるのか、を味わってみてください。


オブジェクト指向設計のスキルが一段階あがることはまちがいありません。


コメント
コメントする









この記事のトラックバックURL
トラックバック
calendar
   1234
567891011
12131415161718
19202122232425
2627282930  
<< November 2017 >>
システム設計日記を検索
プロフィール
リンク
システム開発日記(実装編)
有限会社 システム設計
twitter @masuda220
selected entries
recent comment
  • 番号より名前。 ニーモニックコードより名前。 【パターン】
    師子乃 (03/10)
  • Smart UI が優れている?
    masuda220 (03/10)
  • Smart UI が優れている?
    kagehiens (03/09)
  • オブジェクト指向プログラミングの教え方?
    masuda220 (12/05)
  • オブジェクト指向プログラミングの教え方?
    ZACKY (12/04)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    masuda220 (08/14)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    kompiro (08/14)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    masuda220 (06/13)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    JHashimoto (06/13)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    masuda220 (02/28)
recent trackback
categories
archives
others
mobile
qrcode
powered
無料ブログ作成サービス JUGEM