ひがやすを技術ブログ

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

レイヤモデルアーキテクチャ

レイヤアーキテクチャの場合、ある層は、自分の直接下位の層にのみ依存し、それ以外の層には依存しないのが基本です。通信は、下位の層とデータをやり取りすることで行います。
それでは、このデータはどの層に属するのでしょうか。層に属することにすると、層間で通信するごとにデータをそれぞれの層のデータに変換する必要がでてきます。
例えば、A -> B -> Cという層間の呼び出しの場合、A層のオブジェクトはB層のデータに値を詰めてB層のオブジェクトを呼び出し、B層のオブジェクトは、B層のデータをC層のデータに変換して、C層のオブジェクトを呼び出します。戻り値の処理はこの逆です。B層のオブジェクトは、C層のオブジェクトの戻り値(C層のデータ)をB層のデータに変換して、戻り値として返します。かなり大変です。層が増えれば増えるほどこのオーバーヘッドは大きくなります。
そこで、データ部分は、どの層にも実装上依存しないようにしておくことで、すべての層を通過できるようにしたのが、レイヤモデル(データ部分)アーキテクチャの考え方です。
オリジナルはどこなんだとうざいことを言う人がいるかもしれないので、先に書いておくと、オリジナルがあるかどうかは分かりません。ただ、このように考えるとレイヤアーキテクチャがすっきり説明できるということです。
例えば、プレゼンテーション層、ドメイン層(説明を分かりやすくするためにビジネスロジック層ではなくドメイン層と書いています)、データアクセス層というレイヤがあって、ドメインモデルはドメイン層に属するということにすると、データアクセス層がドメイン層に依存することになり、レイヤアーキテクチャが成立しません。ドメインモデルをドメイン層から分離し、ドメインモデルはドメイン層に仕様上は依存するが実装上は依存しないようにして、すべての層を通過できるようにすることで、レイヤモデルアーキテクチャとしてすっきり説明できます。

ビジネスロジック層とドメインモデル

ビジネスロジック層は次のようなクラス(アプリケーションロジックもドメインロジックも1つのクラス)で構成されます。

  • サービス
  • Dxo
  • アプリケーションロジック
    • メールを送るなどドメインに無関係なロジック
    • ドメインモデルの再利用性を高めるためドメインモデルから分離する
    • アプリケーションロジックをサービスのメソッドにしてしまうとアプリケーションロジックが分散する危険性がある
  • (ドメインロジック)

ドメインロジックを()で囲っているのは、ドメインロジックをドメインモデルに持たせた場合、ドメインロジックは、ビジネスロジック層に含まれないためです。
ドメインモデルにドメインロジックが含まれる場合をリッチドメインモデルと呼び、ドメインモデルにドメインロジックが含まれない場合をシンドメインモデルと呼ぶことにします。
ドメイン層ではなく、ビジネスロジック層という言葉を使ったのは、リッチドメインモデル場合、ドメイン層がなくなってしまうためです。
ビジネスロジック層の構成と処理は、リッチドメインモデルとシンドメインモデルで若干異なることになります。


リッチドメインモデルの検索系の場合、ビジネスロジック層では次のような処理が行われます。

  1. サービスがプレゼンテーション層からプレゼンテーションモデル(検索条件)を受け取る。
  2. サービスはDaoを使って、ドメインモデルを取得する。
    • Employee emp = employeeDao.getEmployee(employeeName);
  3. サービスはDxoを使って、ドメインモデルをプレゼンテーションモデルに変換する。
    • EmployeePresentation empPresen = employeeDxo.toPresentation(emp);
  4. プレゼンテーションモデルをプレゼンテーション層に返す



リッチドメインモデルの更新系の場合、ビジネスロジック層では次のような処理が行われます。

  1. サービスがプレゼンテーション層からプレゼンテーションモデルを受け取る。
  2. サービスはDxoを使って、プレゼンテーションモデルをドメインモデルに変換する。
    • Employee emp = employeeDxo.toDomain(empPresen);
  3. サービスはDaoを使って、ドメインモデルを永続コンテキストに登録する
    • employeeDao.merge(emp);
  4. サービスはドメインモデルのドメインロジックを呼び出す
  5. 必要ならサービスはアプリケーションロジックを呼び出す

サービスのメソッドにはトランザクション用のAOPが設定されているので、メソッドが開始するときにトランザクションが開始され、メソッドが終了するときに、自動的にO/R MapperによりSQL文が発行され、コミットされます。


シンドメインモデルの検索系の場合、ビジネスロジック層での処理はリッチドメインモデルの場合と同じです。


シンドメインモデルの更新系の場合、ビジネスロジック層では次のような処理が行われます。

  1. サービスがプレゼンテーション層からプレゼンテーションモデルを受け取る。
  2. サービスはDxoを使って、プレゼンテーションモデルをドメインモデルに変換する。
    • Employee emp = employeeDxo.toDomain(empPresen);
  3. サービスはDaoを使って、ドメインモデルを永続コンテキストに登録する
    • employeeDao.merge(emp);
  4. サービスはドメインモデルを引数にしてドメインロジックを呼び出す
  5. 必要ならサービスはアプリケーションロジックを呼び出す

リッチドメインモデルとの違いは4の部分だけですね。


サービスをサービス層としてビジネスロジック層から分離していないのは、サービスはデータアクセス層(Dao)を直接(ビジネスロジック層をパスして)呼び出す場合もあるからです。


シンドメインモデルは、ドメインに仕様上は依存していますが、実装上はドメインロジックには依存していません。