行のデータをMapに収容してはいけない理由と、それを解消するMapの実装


行のデータをMapに収容するのはオブジェクト指向的でない、という話があるが本気か」で、ずれたことを書いていた。
Map否定論は、多くはTypesafeの喪失を嫌ったもののようだ。
Javaという静的型付け言語を使うなら、個々のアトリビュートにも、結果表の行全体にも、静的な型を与えないと意味がないのではないの、というニュアンスだな。
●とかいうViewerがないので詳しくは分からないのだが、2chのPC板の過去ログをさらうと、Map擁護派の人が「Map厨」と言われておもちゃにされていた形跡がある。
どういう議論があったのか、かなり知りたい。●、買うか...

Mapを行データのコンテナにしちゃダメな理由

Mapがダメな理由を整理する。
Mapの実装にjava.util.HashMapとかの出来合いを使うことを想定すると、

  • データとロジックが分離してしまう
    • 社員マスタに役員・正社員・パートが収容されていて、それぞれ給与体系が違うとする。全社員一括で給与計算するサービスを作る場合、データが社員インターフェースに包まれていればおしゃれにさばけるが、データがただのMapだとガリガリif分岐しなくてはならない
  • Typesafeの喪失
    • データをgetする時にいちいちキャストが必要
    • getメソッドのキーを間違ってタイプしていても、コンパイル時に検出できない。ヘタすると実行時にも分からないかもしれない
    • customerテーブルの情報を引数とするメソッドを作る場合、Customer型を引数とすれば安全だが、Mapを引数にすると全然関係ないデータが渡されていることをコンパイル時にチェックできない

といったところか。
こういう問題を一掃できれば、コンテナにMapを使ってもいいことになる。

こんなMapを作ります

ここでいうMapとは、データベースフィールド名と値の対応付けをするコンテナ、ぐらいの意味で、別にjava.util.Mapインターフェースを持っている必要はない。
前節の課題に対しては、たとえば

データをgetする時にいちいちキャストが必要
Mapを拡張して getString(), getInt(), getLong(), getDate(), ... を持たせる
getメソッドのキーを間違ってタイプしていても、実行時にも検出できない
存在しないキーでアクセスされたら ColumnNotFoundException という例外を投げる

とか、手の打ちようはある。
Mapだからビジネスロジックを持ってはならない、ということもない。
TypesafeにしたければCustomerというマーカーインターフェースをかぶせればよい。
給与計算をポリモルフィックに処理したければ、給与計算メソッドを持った社員インターフェースを定義して、それをimplementした役員Map・正社員Map・パートMapを実装型にすればよい。


そうまでしてMapをデータのコンテナにする意味は、データを結果表と同じフラットな構造に収容したいから。
create table の写像に堕したオブジェクトグラフを手繰って、データにアクセスするようなプログラムは書きたくないから。