勉強日記

チラ裏

PoEAA ch12 Inheritance Mappers

martinfowler.com


Inheritance Mappers

A structure to organize database mappers that handle inheritance hierarchys.

@startuml
abstract class Mapper {
+ insert(DomainObject)
+ update(DomainObject)
+ delete(DomainObject)
# save(DomainObject, Row)
# load(DomainObject, Row)
}

abstract class AbstractPlayerMapper{
# save()
# load()
}

class PlayerMapper{
+ find(key):Player
+ insert()
+ update()
}

class FootballerMapper{
+ find(key):Footballer
# save()
# load()
}

class CricketerMapper{
+ find(key):Cricketer
# save()
# load()
}

class BowlerMapper{
+ find(key):Bowler
# save()
# load()
}


Mapper <|-down- PlayerMapper
Mapper <|-right- AbstractPlayerMapper
CricketerMapper -up-|> AbstractPlayerMapper
FootballerMapper -up-|> AbstractPlayerMapper

BowlerMapper -up-|> CricketerMapper

PlayerMapper *-right-> "1" FootballerMapper
PlayerMapper *-right-> "1" CricketerMapper
PlayerMapper *-right-> "1" BowlerMapper
@enduml

クラス図

  • DBの保存・読み出しのコード記述量を最少にする
    • 共通処理を基底Mapperに
    • 【補】 Template Method Pattern的な思想
  • 振る舞いの詳細はTable Inheritance系パターンとして何を採用するかにより異なる
    • Single Table Inheritance
    • Class Table Inheritance
    • Concrete Table Inheritance
  • Inheritance Mappersの構造自体は同じ

How It Works

  • DomainModel具象クラスごとに具象Mapperを作る
    • DomainModelのクラス階層と対応
      • FootballMapper
      • CricketMapper
      • BowlerMapper
    • 【補】AbstractPlayerMapperは処理共通化のための基底クラス
    • 機能追加・修正時、変更点は1個所
  • 具象Mapperを束ねるMapperを作る
    • DomainModelのクラス階層の外
      • PlayerMapper
    • 【補】Composite Pattern
  • 具象Mapperのfind(key)メソッドの戻り値の型
    • 静的型付け言語の多くでは、オーバライドした関数の戻り値の型を変ることはできない
      • 【補】PHP7.2新機能: パラメータの反変性・戻り値の共変性
        • 静的型付け言語じゃないけど近づこうという動きの中で生まれた
        • 派生型では...
          • 引数は拡大していい(タイプヒント有 -> 無)
          • 戻り値は縮小していい(タイプヒント無 -> 有)
        • が、タイプヒントの変更はできないはず
      • 抽象型を返すのはNG
        • 呼び出し側でダウンキャストをしないといけない
      • 動的型付け言語では問題ない
    • ので、AbstractPlayerMapperにはfind(key)メソッドがない
  • Mapperを2系統に分割する
    • PlayerMapper
      • 抽象的にPlayerを取得する用
      • insert(),update(),delete()の共通のロジックを定義
    • AbstractPlayerMapper
      • 各具象Mapperクラスの基底
      • 各具象Mapperクラス
        • 各具象DomainModelクラスとDBとのMappingの仕方を知っている
        • save(),load()フックメソッドをオーバライド
          • 【補】Template Method Pattern

When to Use It

  • 使わない場合?
    • コピペ
      • 凶悪犯罪
    • PlayerのインタフェースをAbstractPlayerMapperに混ぜ込む
      • できなくないけど複雑

コード例

  • 採用するTable Inheritance系パターンにより様々
  • 各パターンのコード例を見よ

英語

  • heinous crime
    • 凶悪犯罪