kakakakakku blog

Weekly Tech Blog: Keep on Learning!

TDD のリズムを体験しよう /「テスト駆動開発」を読んだ

今年の1月に書籍「テスト駆動開発」を購入し,1度ザッと読んだけど,まだ書評記事を書いてなく,後回しにしていたらもう9月になってしまった.最近「テスト駆動開発 (TDD : Test-Driven Development)」を教える機会もあるため,改めて本書を読み直し,学べたことを整理しておこうと思う.

本書は TDD を支える「Red / Green / Refactor」のリズムから,「仮実装」「明白な実装」「三角測量」など,重要な戦略の解説もある.そして「多国通貨」を題材とした TDD の体験と「xUnit」を実際に実装しながら学べるように構成されている.個人的に TDD は「名前は知っているけど経験したことがない」人が多くいるプラクティスだと思う.本書を読んで第一歩を踏み出すと良さそう!

目次

  • 第I部 : 多国通貨
    • 第1章 : 仮実装
    • 第2章 : 明白な実装
    • 第3章 : 三角測量
    • 第4章 : 意図を語るテスト
    • 第5章 : 原則をあえて破るとき
    • 第6章 : テスト不足に気づいたら
    • 第7章 : 疑念をテストに翻訳する
    • 第8章 : 実装を隠す
    • 第9章 : 歩幅の調整
    • 第10章 : テストに聞いてみる
    • 第11章 : 不要になったら消す
    • 第12章 : 設計とメタファー
    • 第13章 : 実装を導くテスト
    • 第14章 : 学習用テストと回帰テスト
    • 第15章 : テスト任せとコンパイラ任せ
    • 第16章 : 将来の読み手を考えたテスト
    • 第17章 : 多国通貨の全体ふりかえり
  • 第II部 : xUnit
    • 第18章 : xUnitへ向かう小さな一歩
    • 第19章 : 前準備
    • 第20章 : 後片付け
    • 第21章 : 数え上げ
    • 第22章 : 失敗の扱い
    • 第23章 : スイートにまとめる
    • 第24章 : xUnitの全体ふりかえり
  • 第III部 : テスト駆動開発のパターン
    • 第25章 : テスト駆動開発のパターン
    • 第26章 : レッドバーのパターン
    • 第27章 : テスティングのパターン
    • 第28章 : グリーンバーのパターン
    • 第29章 : xUnitのパターン
    • 第30章 : デザインパターン
    • 第31章 : リファクタリング
    • 第32章 : TDDを身につける
  • 付録
    • 付録A : 因果ループ図
    • 付録B : フィボナッチ
    • 付録C : 訳者解説:テスト駆動開発の現在

仮実装

第1章「仮実装」を読むと「TDD のリズム」をすぐに感じられる.意図的に「歩幅を小さく」し,テストを通すための最小限の変更と言える「仮実装」を活用しながら実装を進めていくため,実装の変化に悩むことなく読み進められる.テストを通すために int amount = 10; を実装したり,重複を発見するために int amount = 5 * 2; に書き直してみたり,初期化部分を times() メソッドに移動してみたりする.まさにリズム!

  1. 小さいテストを1つ書く
  2. 全てのテストを実行し,1つ失敗することを確認する
  3. 小さい変更を行う
  4. 再びテストを実行し,全て成功することを確認する
  5. リファクタリングを行い,重複を除去する

さらに本書の特徴とも言える「口語のような口調」も非常に良く,実際にライブコーディングを見ているような錯覚に陥る.

class Dollar {
    int amount = 10;

    Dollar(int amount) {
    }

    void times(int multiplier) {
    }
}

明白な実装

「仮実装」を使わずに既に考えた実装をコードに落とし込むことを「明白な実装」と言う.第2章「明白な実装」Dollar オブジェクトの状態変化に依存するため,times() メソッドから新しく Dollar オブジェクトを返している.そして TDD では「仮実装」「明白な実装」の間を行き来するという内容も紹介されている.「なぜ "あえて" 仮実装をするの?」というよくある疑問に対する回答になっている.

三角測量

「仮実装」をしていると,たまたまテストが通ってしまうことになるため,別のテストを追加することにより,実装の正しさを確認する戦略として「三角測量」がある.第3章「三角測量」を読むと,Value Object である Dollar オブジェクトに equals() メソッドを実装しながら三角測量を活用している.また本書に載っている通り「設計のアイデアが浮かばないとき」にも三角測量が使えるというのは興味深かった.

public class MoneyTest {
    @Test
    public void testEquality() {
        assertTrue(new Dollar(5).equals(new Dollar(5)));
        assertFalse(new Dollar(5).equals(new Dollar(6)));
    }
}

歩幅

通貨の実装を進めると,誰しも通貨を表現するオブジェクトを作りたくなると思うけど,最初から複雑な実装に進むのではなく,最初は「文字列を活用する」という判断こそ「歩幅を小さく」の具体例と言える.第9章「歩幅の調整」を読むと,Franc.javaDollar.javacurrency() メソッドを追加し,文字列で CHFUSD を返す実装をしてから,コンストラクタに移動したりし,最終的に Money.java にまとまる.TDD の良さを感じられる章だと思う.

リファクタリング

リファクタリングはアプリケーション開発をしているとよく聞く言葉だけど,案外「リファクタリングの定義は?」と聞かれると,人によって違う回答になる.第31章「リファクタリング」を読むと,TDD で使えるリファクタリングのアプローチを学べる.例えば,以下など.

  • データ構造の変更
  • メソッドの抽出
  • メソッドのインライン化
  • メソッドの移動

他にも,書籍「リファクタリング」の第3章「コードの不吉な臭い」に載っている観点も TDD のリファクタリングに使える.合わせて読もう!

TDD を身につける

第32章「TDDを身につける」は個人的に役立った.TDD を教えるときによく聞かれることに対して,全て明確な答えがないとしても「テスト駆動開発」に載っていると言えるのは説得力に繋がる.

例えば,最初に「一歩の大きさはどのくらいか」という疑問が出てくる.本書には「テスト駆動開発者の傾向は "小さなステップ " だけど "大きなステップ" もできるようになるべき」と書いてある.第9章「歩幅の調整」と同じ内容だけど,ステップを飛ばすとしても,自信を持って飛ばせるまでは過剰にでも繰り返すと良いと思う.他にも以下のような疑問に対する言及がある.

  • テストしなくてよいものはあるか
  • どのようなときにテストを消すべきか
  • 巨大なシステムをテスト駆動できるか
  • 途中から TDD に乗り換えるにはどうすればよいか

Cyber Dojo

本書には直接関係ないけど,環境構築に悩むこともなく,サクッと TDD を練習したり,教えたりする場合は「Cyber Dojo」を使うと便利.Python (unittest)Python (pytest)Ruby (RSpec) など,プログラミング言語とテストフレームワークを選び,Fizz Buzz などのお題を選ぶと,すぐに開始できる.

「Cyber Dojo」を使って TDD のサイクルを回すと,実行ごとに「赤 / 黄 / 緑」の結果アイコンも表示されるため,歩幅を小さく進められていることを確認できるのも便利な機能と言える.TDD に限らず「モブプログラミング」の実演にも使える.覚えておくと良いかと!

cyber-dojo.org

まとめ

  • 書評記事を書いていなかった「テスト駆動開発」を読み直した
  • 「多国通貨」を題材とした TDD の体験は実際に写経をしながら進めると効果的に学べる(僕は途中まで写経した)
  • 特に「TDD は知っているけど経験したことがない」という読者層に刺さりそう
  • 本書の最後に載っている「付録C : 訳者解説」もとても印象に残った

あと個人的には,第12章「設計とメタファー」Expression オブジェクトを使って為替レートを考慮した通貨間の計算をする部分は難しく感じた.というよりも,突然「歩幅が大きく」なったような気がして,読んでいてもスッと頭に入らなかった.もう少し「歩幅を小さく」解説があると良さそうに思う.

関連記事

kakakakakku.hatenablog.com