ドメイン駆動を読む(第2部 DDDの応用 第6章 インフラのための準備)
- 実際のデータベースを操作せずに、セーブシナリオのためのテストを書けるようにする
- 目指すところは、インフラに左右されないコードを書くこと
ライフスタイルとしてのPOCO
POCO…Plain Old CLR Object (POJOの.NET版)。FowlerはPI(Persistence Ignorance)という表現を使用
このへんが参考になるかも。
雲のごとく : Visual Studio 2010 EF4 POCO Part1
- PIかどうかを見分けるには、「ドメインモデルにインフラ関連の外部DLLに関する参照が含まれているかどうか」を確認するのがはやい
- 例)O/RマッパーとしてNHibernateを使用している場合、nhibernate.dllに対する参照がドメインモデルのコードに含まれていたら、不吉なにおい
- PIのメリット…TDDにとって好都合である。EntityやValueObjectが明確でクリーンになる
セーブのシナリオの処理
- 論理的なUnitOfWorkを作って、その特徴をセーブに活かしたい
- RepositoryがUnitOfWorkとやり取りするのを筆者は好む
- 「ひとつのシナリオ」が「ひとつのUnitOfWork」「ひとつのIdentityMap」を持つべき
- 集約(Aggregate)はPersistAll()呼び出し時に一貫性の取れた状態になるように設計するべき
- 物理トランザクションとUnitOfWorkは同じでありたい
フェイクメカニズムの構築
- トランザクションを非常に重要な概念として扱わなければならない
- UIプログラマにトランザクション管理の仕事を押し付けたくない
- フェイクメカニズム…2つのレイヤを持つIDマップを使う。
- 第1レイヤ…現在のシナリオで読み出したすべてのEntityを管理する
- 第2レイヤ…永続化エンジンをシミュレート
- GetById()を呼び出したとき、要求された型のIDマップにIDが見つかったらそのまま返す。みつからなければ第2レイヤにフェッチ。返ってきたオブジェクトを第1レイヤにコピーして呼び出し元にオブジェクトを返す。
- すべてのテストがフェイクと本物のインフラの両方で実行できるのは、早い段階でテストが書けるのでよい目標
- フェイクでテストできることにより、リファクタリングに積極的になれる
クエリー
- QueryObjects
- SELECTですべての行を取得し、取得した行数を数えるようなものはまずい
- クエリーとキャッシュ
- GetByQuery()は永続記憶にアクセスする前にIDマップをチェックしない
- 問題:IDマップ/UnitOfWorkに追加されているが永続化されていないCustomerは、IDで問い合わせれば見つかるがクエリーだと見つからない
- 解決策:GetByQuery()はデフォルトで暗黙的にPersistAll()を呼んで、その後DBアクセスする
- クエリーの置き場所