Chapter1 コードの品質
コードの品質とは?と、コードの品質を上げることは開発のスピードを遅らせるわけではないという前提について書かれている。良く言われている基本的な考え方なので、まあ、そうだよね、という感じ。
Chapter2 抽象化レイヤー
コードを抽象的なひとまとまりの単位で分割する考え方。「抽象化レイヤー」に分割することで、可読性、モジュール性、再利用性が高まり、テストもしやすくなるという話。凝集、関心の分離、DI、インタフェースについての考え方など。
最初は3rd partyのライブラリへの依存度を下げるために抽象化層を設けて分離するような話かと思って読み始めたが、そういう観点の話ではなかった。
Part3 ユニットテスト編
Chapter10 ユニットテストの原則
- AAAパターン
- GIVEN, WHEN, THENもあるがテストコード的には同等
10.2 よいユニットテストとは?
- 破損を正確に検出する
- 実装の詳細にとらわれない
- よく説明された失敗
- わかりやすいテストコード
- 簡単かつ迅速に実行する
10.2.1 破損を正確に検出する
ユニットテストの2つの重要な役割
- コードに対して最初の信頼が得られる
- 将来の破損から保護する
「フレーキー」(fleakey)なテスト:脆いテストのこと。
10.2.2 実装の詳細にとらわれない
実装の詳細にとらわれないことの重要さについて、アプローチAとアプローチBで数か月後にリファクタリングした場合の例えがわかりやすい。
- 機能変更とリファクタリングを混在しない
- これも重要。TDD本でよく説明されている。
10.3.1 重要な動作がパブリックAPIの外部にある可能性もある
publicなAPIのみテストするという原則はよく言われる通りだが、『あくまで基本原則であり、「パブリックAPI」と「実装の詳細」の定義は、主観的かつコンテキスト固有のものである可能性を認める必要があります』というのは確かに現実はその通りだと思う。リスト10.1のAddressBookクラスの例えも誰かに説明するのにわかりやすそう。
10.4 テストダブル
テストダブルを使用する理由
- テストを簡単にする
- これは「単体テストの考え方/使い方」では触れられていなかった(と思う)話。テストダブルを使わないことで、逆に実装の詳細と密接に結びついてしまう場合があるのは確かにその通り。
- テストから外側の世界を守る
- テストを外側の世界から守る
- モック
- メンバー関数の呼び出しを記録する機能のみを提供し、クラスorインタフェースをシミュレート
- テスト対象のコードの依存関係で副作用が発生する場合をシミュレート
- スタブ
- 関数を呼び出すたびに定義済みの値を返すことで関数をシミュレート
- 戻り値を提供する依存関係をシミュレート
- フェイク
- テストで安全に使用できるクラスの代替実装
- 例外など本物と同じ仕様を作り込むもの
- モックやスタブのようにテストが実装と密結合になりにくい
10.4.4 モックとスタブが問題になる可能性がある
- モックとスタブの問題
- 実態とかけ離れたテストになる可能性
- 実装と密結合になりリファクタリング困難になる可能性