開発における本書の基本的な考え
- 開発における「予期せぬ変化を予期する」 (anticipate unanticipated changes)
- 開発に「入れ子になったフィードバックループ」を形成する
- ソフトウェアの「 内側と外側の品質」
TDDにおけるポイント
- テストは「設計作業」
- 「失敗するテスト」を書け
- 「エンドツーエンド」のテストを行う
開発は分からない事が多い
- 技術面 … 完全には理解していない
- 要件面 … 顧客は自分たちの組織の事をより深く理解し正していかないといけない
開発では「予期せぬ変化を予期する」必要がある
- 必ず思いもよらないことが起こる
- そもそも誰も行っていな事をやるのがソフトウェア開発
最良のアプローチ
- 実地からのフィードバック、タイムボックスに分割、それをデプロイする
フィードバックをあらゆるレベルに適用する
- ペアプログラミングやユニットテストからリリースまで
重要な技術的な基盤が二つ
- リグレッションエラーを検出する事
- コードを出来る限りシンプルにしておく事
- 書きやすさではなく読みやすさに最適化する
- 常にリファクタリングする
コードを書く前にテストを書く
- 何をしたいのかを先に明確にする
- Red / Green / Refactor
テストを書く事による恩恵
- 受け入れ基準が明確になる
- 疎結合のコンポーネントを書くように促される
- テストがコードの説明となる
- リグレッションの検出するチャンスが増える
テストを実行することによる恩恵
- コンテキストがまだ頭の中にあるうちに、エラーを検出できる
- どうなれば作業を完了として良いのか把握できるようになる
- 余計な実装(金メッキ、gold plating)をしないようになる
- (これは思い当たる節がある人多そう)
テスト駆動開発の黄金律
- 「失敗するテストを書く事なしに、新しい機能を追加してはならない」
コラム: リファクタリング: ローカルに考え、ローカルに実施せよ
- 粒度の細かいリファクタリングを繰り返す
- 大規模な「再設計」とは異なる
受け入れテストを書くことから始める
- ユニットテストだけ書く事の問題
- 不要な機能の実装
- 統合が出来ないケースの発生
- 完了した受け入れテストと実装中の受け入れテストを分ける
端から端まで通したテストを行う
- 相互作用も含めたテストを行う
- デプロイのテストも行う
- 手間がかかるので受け入れテストは自動で行う
コラム: エンドツーエンドテストの重要性: 怖い話
- TDDを行っていたが、必要な実装が行われていない部分があった
- エンドツーエンドテストが行われていなかった
- デモセッションのような物をフィードバックの一環として行うべきだった
(若干独特な定義という噂…)
受け入れテスト
- ドメインエキスパートとの合意をとる
- 既存の機能を壊していない事のチェック
- エンドツーエンドテストとして書く
インテグレーションテスト
- チーム外のコードと組み合わせて動くかどうかのテスト
ユニットテスト
- 本書でメインに解説する
- 外側の質 … 顧客やユーザのニーズにどれだけ応えられているか
- 内側の質 … 開発者や管理者のニーズにどれだけ応えられているか
どちらも同じくらいに重要
ユニットテストによって内部品質を向上できる
- というより、書き換えやすくできるように書かざるを得ない
コラム: 結合と凝集
- 結合 … ある要素を変更した場合に他を変更しなければならない
- 凝集 … 責務が意味のある単位としてまとまっているか