ドメイン駆動設計的テスト戦略
DDD本を読んでいると、ところどころでテストの話が出てきます。
今回は、ドメイン駆動設計において、テストをどう書くか。ということに焦点を当てて行きたいと思います。
[前提] ドメイン駆動設計は自動テスト必須
ドメイン駆動設計でのモデルは、イテレーションを通じて進化していくことが前提とされています。
ですので、アジャイルで開発することが期待されています。
アジャイルではスプリント期間中にテストを終わらせるため、テスト自動化に取り組む必要があります。
ドメイン駆動設計でも同様に、テスト自動化は必須のプラクティスとなります。
モデルを実際に使うためのテスト
設計の意図が明らかになるように、型名・メソッド名・引数名などを正しい名前に揃えるという意図の明白なインターフェイス。
意図の明白なインターフェイスを設計するためにテストを活用できます。
振る舞いを実装する前にテストを書いて実際にモデルを使用してみることで、モデルを利用する側の視点が得られ、意図の明白なインターフェースを見つけやすくなります。
値オブジェクトのテスト
値オブジェクトは基本、副作用のない関数になります。
同じコマンドを同じように実行したら同じ値が返って来る関数が副作用のない関数。
なんども実行されるテストにとって、副作用のない関数は書きやすいですね。
さらに、閉じたクラスを併用するともっと書きやすくなるでしょう。
エンティティのテスト
どうしても副作用の出てしまう関数のテストをどうするかというと、表明を使います。Entityでどうしても状態を変更するときなどに使用します。
表明はテストで表現することもできます。
メソッドが取りうる条件と、テストで実行した結果が合っているかをテストで書いておくことで、表明としての事前条件と事後条件を表現することができます。それがドキュメントとして利用できるということですね。
境界のテストは超重要
ドメイン駆動設計において、コンテキストの境界を設置して、適切な大きさのモデル・チームでモデルを構成していくことが大事になってきます。
その境界間を統合するいくつかの戦略がありますが、別々の道を選択しない限り、どの選択をしてもその統合は困難です。
境界の統合は継続的な統合を利用して統合します。
概念的な統合が重要ですが、技術的にCIを利用して、モデルの分裂に対して素早く警告する自動化されたテストが必要です。
共有カーネルを選択したときのテスト
統合に共有カーネルを選択した場合は、頻繁に統合し、境界の両側のテストが通ることが大事です。
顧客/供給者の開発チームを選択したときのテスト
統合に顧客/供給者の開発チームを選択した場合は、受け入れテストを共同で開発することが大事です。
開発したテストは上流側のテストスイートに追加し、継続的な統合の一部として実行されるようにします。
腐敗防止層を選択したときのテスト
統合に腐敗防止層を選択した場合は、腐敗防止層が、それ自体で複雑なソフトウェアになりえることに注意します。
その分テストが大事になってきます。