PoEAA ch10 DataMapper
Data Mapper
A layer of Mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself.
How It Works
- Domain層とData Source層との分離が本層の主要な役目
- 考慮すべきこと多し
- O/Rマッピングのロジックが複雑な場合に有効
- 更新系
- create, update, delete
- トランザクション境界としてUnit of Workを用いよ
- オブジェクトグラフの取得について
- Data Mapperいくつ作る?
- 手でコーディングしているならDomain Objectや、そのグラフのrootのクラスにつき1つ
- 【補】DDD界隈でEntityやAggregateと呼ばれるヤツのことか
- Metadata Mappingで自動生成しているなら単一でもよい
- 単一クラスに大量のfindXxxメソッドが生えることになる
- 手でコーディングしているならDomain Objectや、そのグラフのrootのクラスにつき1つ
- Identity Maps
- RDBから読み出したオブジェクトの一意性の維持
- 【補】1つの主キーに対し、メモリ空間上1つのオブジェクト
- どこにおく
- Registryに置く
- 【補】Singletonみたいなやつ
- Finderの中に置く
- Registryに置く
- RDBから読み出したオブジェクトの一意性の維持
Handling Finders
- Domain Objectからfindメソッドを呼びたいケース
- Lazy Loadを適用すれば、Domain Object内での明示的な呼び出しコードは回避可能
- 【補】associationをたどると暗黙裡にデータ読み込み
- シンプルなアプリケーションでは大げさ
- でもDomain ObjectからData Mapperへの依存は避けたい
- Separated Interfaceを適用せよ
- Finderインタフェースを切り出す
- Lazy Loadを適用すれば、Domain Object内での明示的な呼び出しコードは回避可能
Mapping Data To Domain Fields
- Data MapperはDomain Objectのフィールドにアクセスする必要がある
- でもフィールドをpublicにはしたくない
- 簡単ではない問題
- オブジェクトの生成についても同様の問題がある
- とるべき道は2通り:
- rich constructor
- empty object + Lazy Load
- 著者は前者好み
- 構築時点でwell-formedなオブジェクトが得られる
- immutableにできる
- フィールドをmodifyするpublicメソッドを生やさない
- rich constructorの問題点
- 循環参照
- 構築時に無限再帰に陥る
- どう回避する
- rich constructorをやめ、empty object + Lazy Loadにする
- Identity Mapに登録があればそれを読み出す
- なければ空のオブジェクトを生成し、即座にIdentity Mapに登録する
- rich constructorをやめ、empty object + Lazy Loadにする
- 循環参照
- empty objectの場合、immutableをどう実現するの問題
- 先述の解決法に同じ
- 特定のコンテキスト外で呼び出されたら例外送出
- 特定のコンテキストで使ってほしい旨を名前で表現する
- リフレクション
- 先述の解決法に同じ
- とるべき道は2通り:
Metadata-Based Mappings
- マッピングの知識どう表現する
- コードで明示的に書く
- Metadata Mappingで自動生成する
When to Use It
Example
- 実装してさんざん悩んだことあるから略