MVC、本当にわかってますか?

  • 791
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

ウェブアプリケーションフレームワークのMVCは、大きく分けてプッシュ型、プル型があります。

--

こんにちは、タイトルはいつも通り釣りです!
今、ウェブアプリケーションフレームワークを物色中です。
そのいろいろ見ているうちに、頭のなかにごにょごにょあったことを吐き出すのを目的にしています。
他の視点でまだ続くかもです。

例のごとく間違ってたらまさかりよろしくです!!

--

MVCとは?

表示が伴うフレームワークの基礎、MVCを、なぜこれが必要になったのか、順を追っておさらいしたいと思います。

最初は一つ V

一般的に、分割すると複雑になります。複雑は悪です。なので最初はすべて一つに詰め込む、と考えてみましょう。

HTMLにJavaScriptを直書きしてる状況を思い浮かべてください。最初は上手く行くかもしれませんが、比較的早い段階で大変なことになります。なぜなら……

  • プログラマは必ずしもデザインの専門家ではない

見た目は、一番外側にある中身です。
中身はいいんだけど外側が……なんてのは通用しません!!

なので見た目も当然こだわりたい。ですが問題になるのは、プログラマは、必ずしもデザインの専門家ではないということです。

ここに分割の必要性がまず発生します。

  • 見た目の変更は激しい

自分はプログラマだけどデザインもできるよって?すばらしいです!!
ですが依然として分割は必要なんです。

デザインの変更は機能の変更にくらべて、頻繁に行われることが経験的に知られています。

単なる座標変更で話がすめばいいのですが、ここのボタンは0.3秒で右にスライドアウトして、等々、コードが絡んでくる可能性もあるわけです。
このとき、一枚岩だと、三ヶ月後.。(どのメソッドだっけ……)とソースを探険する際、大きな労力を必要とします。

次は二つ M V

なのでビューを分けましょう。表示をView、中身をModelとします。

この分割は、またある程度までは上手く行きます。ですが、こんなシナリオを考えてみましょう。

チェックボタン1、2、3がある。1、2がチェックされたら画面Aへ、1、3がチェックされたら画面Bへ、それ以外はアラート

このように、複雑なウィジェットの条件分岐がある場合です。どちらに書くのが適当でしょうか?

Viewに書く場合

見た目に関わることだからビューに書きましょう。と言う訳でViewに書きました。問題無さそうですね。

さて、新たな要件が発生しました。文言を表示して、チェックボタンが三つある画面を作る必要があります。レイアウトは統一感と出すため、以前作ったものと同じにしてほしいらしいです。
ただし、今回は三つのうち一つだけチェックが入ったら次の画面へ遷移します。

どうしたものでしょうか?困りました。
困ったので、コピペして変更することにしましょう!!

しばらくして、レイアウトの修正要件が入りました。すると……

Modelに書く場合

ひどい夢をみました。コピペして重複コードを量産して、その重複コード一つ一つにパッチを当てる夢です。まったくひどい夢です!!

ウィジェットによる条件分岐は中身の仕事じゃないでしょうか。そうでしょう、そうなんだ!
なのでModelにこのロジックを書きました。問題無さそうですね。

そうしてモデルはどんどんUIの条件分岐判断コードが増えて、巨大になりました。めでたし、めでたし。

よろしい、ならば分割だ! M V C

そうなんです、上の条件分岐、どちらに属しても面倒なんです。今こそ分割のときです。先のロジックをおく場所をControllerとします。
Controllerの責務は、

UIの低レベルなイベントを受け取って、より意味のある大きなイベントに変換することです

この責務の意味はとても重要です。この意味を理解しないと、ぶくぶくふとったControllerを作ってしまいます!!

MVC小まとめ

こうしてできた(のかどうか知りませんが)アーキテクチャを、Model-View-Controller、頭文字を取ってMVCと呼びます。
おのおのの責務をまとめますと、

  • Model: ビジネスロジックを記述する。
  • View: Modelを表示する。
  • Controller: Viewの入力を受け取って判断し、Modelを起動する。

Model<->View間の接続はどこいった?

さて、上の分割、問題が一つ残っています。ModelとViewの接続です。ModelがViewを直接参照すると、Controllerをわけた意味がありません。ここに二つの戦略が発生します。

ControllerがModel-View接続を担当する(aka MVP, Push-MVC ,Passive View)

ModelとView、両者を知っているのは、現時点でControllerしかいません。よってControllerにがんばってもらおう、という戦略です。
これはGUIの世界ではMVPと呼ばれますが、ウェブの世界ではPush-MVCと呼ばれています!(最初混乱しました)
Controllerが、ViewにModelの情報をPushすることから、Push-MVCです。

そして、ViewはControllerがトリガになって更新されるため、受け身です。このことから、このViewのことをPassive Viewと呼んだりします。

ViewがModelを参照する(aka Pull-MVC)

ModelはView無しには存在し得ますが、ViewはModelのデータに依存しています。この依存関係を忠実に再現すると、ViewがModelを参照すればよいことになります。

この構造を、ViewがModelからデータを引っ張ってくる(pull)とこから、Pull-MVCと呼びます。GUIの世界でMVCといったら普通こちらを指します。

フレームワークの選択

さて、MVCといってもPushとPull、二つの戦略があると言う話でしたが、ウェブアプリケーションフレームワークでは、どちらが主に使われているのでしょうか。

結論を言えば、Push-MVCです。大きな理由としては、Viewをブラウザー、Cをルーティング、Mをビジネスロジックとするならば、VとCMの間には、HTTPという巨大な壁があるからです。

Pull-MVCを素朴に実装しようとしたら、ブラウザから頻繁に問い合わせをかける必要があります。
なので、Pull-MVCで作られていると呼ばれるフレームワークは、HTMLのレンダリング時に、Modelを参照するようにできています。
まだ問題はありまして、HTTPはステートレスであるという点が、ViewがどのModelに関連付けられていたのか、という情報を失わせます。
これを回避するため、セッションにViewとModelを関連づける情報を保持する必要があります。
そのため、Pull-MVCのフレームワークは実装が難しく、あまりメリットがないので、少ないのが現状なようです。

ですが、特定のウェブアプリにおいては、状況が変わってきました。

HTML5です。
ここではHTMLをクライアントサイドでごにょごにょする技術のバズワードとします。

これはViewを再定義するのに十分なインパクトがあったのです。HTML5以前は、HTMLの変更を行うためには、サーバに問い合わせが必要でした。ですが、HTML5はViewのダイナミックな変更を可能にします。これにより、

(Browser)View -|Network|- (Routing)Controller - (Logic)Model

を、

(Browser)View - Controller -|Network|- (Logic)Model

に再定義できます。
この定義になると、Push-MVCは、Model情報を一度に転送しないとならないため、逆に都合が悪くなります。

いまはまだ過渡期のようですが、Synthのように、この再定義に乗っ取ったフレームワークも登場しているようです。

ただし、SEOの都合や、コンテンツが主役のアプリ等、Push-MVCのフレームワークが無くなることはないでしょう。
ですがこの構図をしっかり頭にいれたら、Push-Pullが混在する複雑なアプリを作る際、一定の指針になるのではないでしょうか。

以上です!!いいフレームワークあったら教えてください!!