勉強日記

チラ裏

PoEAA ch11 Identity Map

martinfowler.com


Identity Map

Ensures that each object gets loaded only once by keeping every loaded object in a map.
Looks up objects using the map when referring to them.

  • 一貫性
    • 時計が2つあると何時だかわからなくなる
    • DBからオブジェクトをロードするときも同じ
  • パフォーマンス
    • DBのリモートアクセスを1回で済ませる

How It Works

  • 単純なケースでは、1map1テーブル
    1. テーブルからロードする前に、mapを見る
    2. ロードしようとしている対象がmapにすでにあれば、それを返す
    3. なければ、DBアクセス
  • いろいろ考えることある(下記)
  • 並列処理問題も考える必要あり
    • Optimistic Offline Lock (未習)

Choice of Keys

Explicit or Generic

  • explicit/generic
    • explicit: findPerson('1')
    • generic: find('Person', '1')
  • メリデメ
    • 著者(Martin Fowler)はexplicitのほうが好み
explicit generic
再利用性 x o
コンパイル時チェック o x
参照とか追いやすい o x
map追加のたびにメソッド追加しなくていい x o
色々な型のキー使える o x

How Many

セッションに1つ

  • 制限
    • キーがDB中一意である必要がある
      • Identity Field (未習) 参照
  • 利点
    • 置き場が1箇所
    • 格納対象のオブジェクトが「継承」しているときの悩みがない
    • テーブル追加時にmapを追加しなくていい

クラス/テーブルにつき1つ

  • オブジェクトとDBスキーマとが一致している場合は「テーブルにつき1つ」でいい
    • 【補】Active Recordとか?
  • そうでない場合は「クラスにつき1つ」がよい
  • 継承どうすんの問題
  • 例: 車 extends 乗り物
    • 車Map乗り物Map分ける?
      • クライアント側は乗り物派生Mapを全部見ないといけないので不便
    • ゆえに著者は「分けない」派
    • ただし、Concrete Table Inheritanceパターン採用時は問題がおこる
      • 「分けない」場合、継承ツリー全体でキーを一意にしないといけない
      • 【補】Concrete Table Inheritanceは、具象クラス1つにつき1テーブルを割り当てるパターン
        • 基底クラスに対してはテーブルを作らない
        • ので、「継承ツリー全体でキーが一意である」ことを、DBの一意性制約では担保できない
          • carsテーブルとbicyclesテーブルとで同一のPK値を割り当てることができてしまう

Where to Put Them

  • 1セッション1mapの場合
    • Unit of Work (未習)を採用しているならそこが最適
    • さもなくば Registry
      • 【補】DIコンテナはこれにあたるのかな
  • 1セッション1mapじゃない場合
    • RDBのキャッシュとしてオブジェクトDBを利用している場合
      • 【補】オブジェクトDBじゃないけどRedisとか
      • 【補】Identity Mapを使わずとも、セッションをまたいでキャッシュが効く
    • read-onlyな場合
      • Identity Mapのそもそもの動機のひとつが「一貫性」
      • modifyしないならオブジェクトが複数あっても更新時異常がおきないので問題ない
      • が、パフォーマンス目的で設けることはある
      • read-onlyなIdentity MapとupdatableなIdentity Mapを分ける
        • read-only
          • パフォーマンス目的
          • プロセスコンテキスト
        • updatable
          • データ一貫性目的
          • セッションコンテキスト
          • 【補】1req/resごとに1プロセスの場合、1セッションは複数プロセスからなる

When to Use It

  • いつ使わない
    • modifyしない
  • が、使ってもいい
  • セッションをまたいでの更新異常には無力であることに注意する
    • 参照:
      • Optimistic Offline Lock (未習)
      • Pssimistic Offline Lock (未習)

Example: Methods for an Identity Map

    • ただのsingletonなmapのラッパ