オブジェクト指向とMVC(Model-View-Controller)と3層クライアントサーバってちゃんぽんして理解している人って多いと思う。
特にVC++やC#のプログラマに多いんじゃないかしら。
オブジェクト指向の本質と、MVCの本質と3層クライアントサーバを、ちゃんと理解してない人が、自分も含めて多いことに気がついたんで、説明がてら、自分の理解を整理してみる。
さて、オブジェクト指向の考え方の一つとして、データとそのデータと関連性の強い手続きをひとくくりにしておく、というものがある。C++いうところの、メンバ変数とメンバ関数を集めたクラス、オブジェクトという考え方である。この先にはメンバ関数で、メンバ変数の操作を隠ぺいするという考え方につながっている。
MVC(Model-View-Controller)では、モデル-ビュー-コントローラの3つの部分に分割して考える。
ユーザーはViewを操作する。Viewからの入力イベントをControllerが処理する。ControllerがModelのメソッドを呼び出し、Modelのデータが更新される。ViewはModelのデータを取得しユーザーインターフェースを更新する。
ここまでは何の問題もない。
さて、C#なり、VC++なりで、MVCを用いて実装しようとした場合に、とたんに、混乱する人が多い。
C#なり、VC++なりで、ユーザーの操作した入力イベントを受けようとすると、C#ならばFormクラス、VC++ならCWndまたはその派生クラスにイベントハンドラを記述する。
しかし、MVCでは、入力イベントはControllerが処理するはずである。
何も考えないで、実装を進めると、本来ならばViewの部分にあたる、Formクラス、CWndまたはその派生クラスに、Controllerの内容が実装されてしまう。
これに加え、先の、メンバ関数で、メンバ変数の操作を隠ぺいするというオブジェクト指向の考え方が、拍車をかける。Formを操作するメンバ関数が、CWndやその派生クラスを操作するメンバ関数が、それらのクラスに用意されているので、どうしても、イベントハンドラの実装が膨らんでしまう。
ViewとControllerが必要以上に密接につながってしまう。
まぁViewとControllerは密接につながることが多いので、これはやむをえないことかもしれない。VC++では、MFCにおいては、MVCではなくDoc-Viewを提供しているのも、それはそれで納得できる話だと思う。
次に、3層クライアントサーバ。3層クライアントサーバでは、プレゼンテーション層、ファンクション層、データ層に分割して考える。
プレゼンテーション層では、ユーザからの入力を受取り、ファンクション層を呼び出す。ファンクション層ではビジネスロジックを処理し、データ層を呼び出す。データ層では、データを更新する。データ層で更新されたデータは、ファンクション層を通って、プレゼンテーション層に渡され、ユーザへのフィードバックとなる。
ここでは、MVCでいう、ViewとControllerの関係は、3層クライアントサーバでのプレゼンテーション層の中に入っている。Viewがプレゼンテーション層、Controllerがファンクション層に対応しているわけでは決してない。
同様に、MVCでいう、Modelは、3層クライアントサーバでの、ファンクション層とデータ層を表している。
3層クライアントサーバで実装していると、データ層ではストアドプロシジャなどに、どんどんビジネス層が混ざりこんでくる。先のオブジェクト指向の考えでいくと、メンバ変数とメンバ関数が一か所に集まっているのが正しいので、どうしても、混ざりこむ方向に進みがちである。
特に最近のデータベースやサーバ商品は一つの記述力が高いので、まぜこぜにしやすい。
怪しいなと思ったときには基本に立ち返るべきである。
なぜ、MVCではControllerを分離する必要があったのか。
なぜ、3層クライアントサーバでは、ビジネスロジックとデータ層を分離する必要があったのか。
まぁアーキテクチャなんてものは、ルールの一つでしかないので、その場その場の問題において臨機応変に境界線をずらすのは当然なのだが、丁寧に基本を考えると見えてくることもあると思う。