Help us understand the problem. What is going on with this article?

MVC の Model 肥大化への対処

More than 3 years have passed since last update.

MVC とは何かを 1 から学ぶ で投稿した内容の続きとして、MVC の問題点についてどう対処するか、についてまとめていきます。

MVCの問題点 (再掲)

  • 業務で扱うデータ要件が複雑になればなるほど、Model が肥大化していく (今回のテーマ)
  • 入力に応じた出力要件が複雑になればなるほど、Controller と View の依存性が高くなる

Model の肥大化とは…

例えば、Issue 管理のための Web アプリケーションを作成するとします。
Web の画面から、ユーザが Issue を閲覧・登録・更新・削除出来るようにする場合、以下の実装を担当するのはどこでしょうか。

  • DB に格納された Issue から、未完了のものを取得する
  • ユーザが更新 / 削除するために選択した Issue の詳細情報を取得する
  • ユーザが更新 / 削除するために選択した Issue が完了済でないかチェックする
  • 画面から更新された Issue を DB に反映する

…答えはすべて Model です。

Controller はこの Model の状態を View に渡し、View は Model の状態を参照して画面に返すだけなので、上記のようなビジネスロジックを実行し、データ ( ここでは Issue ) を操作するのは全て Model となります。

このように業務機能や、扱うデータ要件が複雑になるほど、Model が担う役割が多くなる = 肥大化することは容易に想像がつきます。

Model 肥大化 への対処

レイヤアーキテクチャの導入

そこで、 MVC のアーキテクチャパターンに、アプリケーションのレイヤ構成を当てはめ、肥大化する Model を分割します。
MVC の設計上、Model が担う役割自体を減らすことは出来ないので Model の中の役割分担を明確にし、煩雑に肥大化していくことを防ぎます。

レイヤ化

レイヤ化にも色々な種類が存在しますが、例として 実践ドメイン駆動設計 で述べられている 以下の 4 層をもとに整理していきます。

  • UI 層 (プレゼンテーション層)
  • アプリケーション層
  • ドメイン層
  • インフラストラクチャ層

UI 層 (プレゼンテーション層)

  • ユーザのリクエストを受付け、レスポンスを画面に表示する層。

アプリケーション層

  • アプリケーションをコーディネートする層。プレゼンテーション層から受取ったリクエストをハンドリングし、ドメイン層を使ってアプリケーションを実行する。

ドメイン層

  • Domain Object を持ち、Domain Object に対するアプリケーションのビジネスロジックを実行する。

インフラストラクチャ層

  • ドメイン層の実装を持つ層。Domain Object に対する CRUD 操作の実装を提供する層。DB に接続し、データの CRUD 操作を行うことで DB を永続化する。

MVC との対応関係

  • UI 層 : View
  • アプリケーション層 : Controller
  • ドメイン層 : Model

( インフラストラクチャ層 : Model が 保持する Domain Object に対する CRUD 操作の実装 )

ドメイン層とインフラストラクチャ層の分割

ここで更に、肥大化する Model ( = ドメイン層 ) を更に以下の役割に分割します。

ドメイン層

  • Domain Object
    ビジネスロジックを実行する上で必要な資源。Entity。POJO。

  • Repository
    Domain Object の CRUD 処理を行うインターフェース。
    Repository は DB アクセスの実装は持たず、ルールの定義のみ。

  • Service
    アプリケーションのビジネスロジック。

インフラストラクチャ層

  • RepositoryImpl
    ドメイン層で定めた Repository の実装をもつ。
    O/R Mapper を使用してDB に接続し、Domain Object の CRUD 処理を行う。

  • O/R Mapper
    DB と Entity のマッピングを行う。

各レイヤ間の関係は以下の図の通りです。

図1.png

上記の図で押さえるポイントとしては 2 つです。
1. ドメイン層 (Model) は アプリケーション層から使用・参照される
2. ドメイン層 (Model) は インフラストラクチャ層のインタフェースを定義

つまり、ドメイン層はどこの層にも依存していないことになります。インフラストラクチャ層の実装が変わったとしても、ドメイン層ではインタフェースを定義しているのみのため影響を受けません。

こうしてアプリケーションをレイヤ化し、分割することで Model が疎となり、煩雑な肥大化を防ぐことが出来ます。


例えば Java の Spring Framework を使用すれば @Service@Repository アノテーションを付けるだけでフレームワークが上手く処理してくれるのですが、書く側が理解して設計できないと、プログラムが少し複雑になっただけで応用が効かなくなりそう ( 効かなくなって自分の首を締めた経験あり ) ということで整理してみました。

参考

DDDを踏み外してからもう一度踏み出してみた - hatajoeのブログ
実践DDD本の第4章「アーキテクチャ」 ~レイヤからヘキサゴナルへ~ (1/4):CodeZine(コードジン)
2.4. アプリケーションのレイヤ化 — TERASOLUNA Server Framework for Java (5.x) Development Guideline 5.3.0.RELEASE documentation

tentom
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした