ひがやすを技術ブログ

電通国際情報サービスのプログラマ

レイヤとモデル

アプリケーションをレイヤ分割した場合、

プレゼンテーション層 -> ビジネスロジック層 -> データアクセス層

のように分けるのが一般的ではないかと思います。
ここで、矢印は、依存関係を表しています。例えば、プレゼンテーション層は、ビジネスロジック層に依存していて、ビジネスロジック層は、データアクセス層に依存しています。
矢印の向いていないほうには依存していません。例えば、ビジネスロジック層は、プレゼンテーション層に依存していません。
誤解が多いんじゃないかと思うのは、レイヤとモデルを混同することです。一番多く見られるのは、ビジネスロジック層とドメインモデルの混同です。
モデルは、各層を流れていくデータ(+ ロジック)であり、どの層にも依存しません。逆に層はモデルに依存することになります。
モデルは、プレゼンテーションモデルとドメインモデルに分かれます。本当は、ERモデルもあるのですが、ここでは対象外とします。ここでのモデルは、外部スキーマ、概念スキーマ、内部スキーマといわれているものに対応します。
プレゼンテーションモデルとドメインモデルが一致する場合もありますが、概念的には分けていた方がいいでしょう。プレゼンテーション層には、ドメインモデルの複雑な構造を見せるべきではありません。あくまでも、プレゼンテーション層にとって最も扱いやすいプレゼンテーションモデルを使うべきです。
例えば、従業員の管理画面で従業員の所属する部署名も表示する必要があったとしましょう。ドメインモデルとしては、従業員オブジェクトから部署オブジェクトを取得し、そこから部書名を取得することになります。
プレゼンテーションモデルの場合は、従業員プレゼンテーションオブジェクトに部署名を持たせることになります。
このようなプレゼンテーションモデルとドメインモデルの変換を行うのがDxo(Data eXchange Object)です。これは、私が付けた名前ですが、ドメインモデルとERモデルの変換を行うDaoと比較すると分かりやすいのではないかと思います。
ビジネスロジック層では、データアクセス層から取得したドメインモデルをDxoを使ってプレゼンテーションモデルに変換してプレゼンテーション層に渡し、逆にプレゼンテーション層から受け取ったプレゼンテーションモデルをDxoを使って、ドメインモデルに変更してビジネスロジックを実行します。
Dxoを使う副次的な効果として、プレゼンテーション層でのlazy loadingを避けることができるというものがあります。
例えば、先程の従業員オブジェクトから部署を取得する部分にlazy loadingが適用されていたとしましょう。Dxoを使わない場合でも、プレゼンテーション層では、employee.department.departmentNameのように部署名を取得することができますが、lazy loadingが適用されているとdepartmentを参照した瞬間に部署を取得するためのSQL文が発行される危険性があります。プレゼンテーション層、例えばJSPでエラーが起きると適切なエラー表示をすることが難しいことも多いので、できる限りそのような状態は避けなければなりません。Dxoを使うとビジネスロジック層でデータの取得(従業員プレゼンテーションオブジェクトの部署名に部署オブジェクトの部署名が設定される)が終わっているため、このようなエラーを避けることができます。
整理すると、プレゼンテーション層は、プレゼンテーションモデルとビジネスロジック層に依存します。ビジネスロジック層は、ドメインモデルとデータアクセス層に依存します。データアクセス層は、ドメインモデルに依存します。プレゼンテーションモデル、ドメインモデルのどちらもどの層にもお互いのモデルにも依存しません。
Dxoでの処理は多くの場合、機械的に出来る可能性があります。Seasar2では、アノテーションAOPを利用して、S2DaoのようにDxoでの処理を自動化するフレームワークS2Dxoを提供する予定です。
それでは、ビジネスロジック層ではどのような処理を行うのでしょうか。これについてはまた今度お話します。


補足:lazy loading
lazy loadingとは、データのロード(フェッチ)を必要になるまで遅らせる技法です。ドメインモデルは、関連がいくらでもネストする可能性がありますから、すべての関連を最初に解決するととんでもないことになることもあるので、このような技法があります。もちろん、不要なフェッチを抑えることで、パフォーマンスを向上させるという目的もあります。
lazy loadingはO/R Mapperによって自動的に解決されます。
例えば、Employeeクラスにdepartmentプロパティがあった場合、departmentプロパティにアクセスしたときに、透過的(意識せず)に処理されるのです。
Dxoを使わない場合、プレゼンテーション層でdepartmentプロパティにアクセスしたときに、透過的にO/R Mapperによるフェッチが行われSQL文が知らないうちに発行される可能性があるのです。