GenerationGapパターン

いま組み込まれているプロジェクトでは、ツールによってソースコードの自動生成を行なうことが多く、頻繁にジェネレーションギャップパターンという言葉を聞くため調べてみました。
http://www.hyuki.com/dp/dpinfo.html#GenerationGap
昔にCマガで読んだ鴨。上記結城さんのサイトで分かりやすく説明されていますが私なりの簡単な解釈を以下に。

  • 自動生成されたクラスの「動作」を変更したい場合等に自動生成されたコードそのものを書き換えるのではなく、継承したクラスを作成してメソッドのオーバーライドで動作の変更を行なう。
  • アプリケーションコードからは、継承したクラスを使用する。自動生成されたコードは使用しない。
  • これにより再び自動生成を行なっても、ユーザによって追加されたコードが消えることは無い。


GenerationGapパターンの適用対象となるのは、もちろん自動生成されたクラスになるのですが、自動生成されたクラスがなんでもかんでもGenerationGapパターンの対象になるわけでは無いと思います。

今の仕事では Hibernate が自動生成したエンティティクラスを継承してドメインモデルのクラスを作っているのですが、ドメインモデルとDBのテーブルが1:1対応するとは思えないですし、DBカラムの型とドメイン層で扱う型は異なるので*1*2、いろいろと弊害が出ています。

エンティティクラスを継承してドメインモデルを実装している理由を技術リーダにたずねたところ、

  • アプリケーションコードからDBの値を取得するときに、ドメインモデル経由で取得したい。しかしコード記述量は抑えたい。
  • GenerationGapパターンによってDBのカラムを変更した場合でも、再び自動生成するだけで対応したコードが出力される。

らしいですが・・・

私が思うに、

  • GenerationGapパターンはユーザが記述したコードがコードの再自動生成時に消えてしまわないようにするものであり、コード記述量を減らすことを目的としたパターンでは無い
  • コード記述量を減らすために継承を利用しているが、通常は委譲によって解決するケースに対して継承を使用している。
  • また継承を利用する大義名分としてGenerationGapパターンを挙げているが、GenerationGapパターンを使う必然性がまるで無い。
  • HibernateのエンティティはDBとのやり取りに使用するデータのためのクラスであり、ロジックな部分はエンティティクラスとは別な場所に記述する必要がある。

とか。


なんか、愚痴の塊な文章になってしまった・・・GenerationGapパターンについて書けていないorz
これだけではしょうがないので、私の中での結論を以下に。

  • GenerationGapパターンは、自動生成したクラスに手を加えなければいけない場合に使用。自動生成したクラスの情報が欲しい場合や機能を利用したいだけの場合は委譲で解決。*3
  • 継承よりも委譲を。フレームワーク的なクラスでTemplateMethodパターンを使う場合等を除いて、ほとんどの場合は委譲で解決できるし、するべき。*4




追記: 歪んだOO原理主義な方は無理にデータと処理を一緒にしたがります。特定テーブルのエンティティにビジネスロジックをくっつけたがるのはどうかと。
ビジネスロジックが必要とするデータがそのテーブルだけで完結するわけはありませんから、残念!
1つのクラスに一つの責務を忘れずに。
ちょっと関連がありそうなデータに誤ってロジックをくっつけてしまうのはOOやり始めのころに私もよくやったなぁとおもったり。これがOOだっ!とかおもって(汗)。もう10年近く前の話しですが(w
OOの定義は人によって千差万別。データとロジックがくっついていないからといってOO出来ていないとは言えないと思う今日この頃です。(かといって構造化ってことじゃないですよ(^^;ゞ)

*1:DBの区分値はJava上ではTypeSafeEnumな定数値だったり

*2:Hibernateマッピングを適切に記述すればエンティティクラスがもつプロパティ値をTypeSafeEnumとすることも可能だとは思いますが

*3:ってあたりまえか。

*4:委譲の方がなにかとメリットが多いので。いまさら言うまでもないですね。