MVCパターンの適用限界を考える(3)

さて、2つ前のエントリーに書いた図1-1図1-2の最もシンプルなMVCパターンでは、すぐに行き詰まることを多くの人が知っている。というか、これではControllerがメニュー画面を出すことすらできない。Controllerの定義から、メニュー画面はControllerそのものであるが、画面表示するにはModelを変更するしかないからである。

まさか、ControllerがViewに依存しないように、メニュー画面のイメージをModelに送るようにすることはあり得ない。多少はViewの使い方を知っていてViewに対するメッセージをModelに渡すなら、それはControllerがViewに依存していることになるので無駄である。Viewへのメッセージの文法を知っているなら直接Viewにメッセージを送れば良い。

ViewとControllerとの間に関連も依存も無いMVCが最も美しい、と考えるあまり、メニュー画面の動作をもModelに含めるのが正しい、突き詰めると、アプリケーションの動作は全てModelにあるのが正しい、と考える人は少なくないが、それは本来のMVCパターンではない。
実は、originalなMVCに答えがある。

"MODELS-VIEWS-CONTROLLERS"のControllerの定義より
It provides means for user output by presenting the user with menus or other means of giving commands and data. The controller receives such user output, translates it into the appropriate messages and pass these messages on to one or more of the views.
(訳:Controllerは、ユーザーにメニューを見せること、または他のコマンドとデータを渡す手段により、ユーザーからの出力手段を提供する。Controllerはユーザーからの出力を適切なメッセージに変換し、そのメッセージを1つ以上のViewに渡す。)

つまり、元々、メニュー画面のようなControllerの表示は、Controllerが直接Viewにアクセスすることによって行うという考え方なのである。図にすると次のようになる。

Class diagram of MVC with V-C connection
図2-1: Controllerの表示が可能なMVCのクラス図(静的構造図)

Communication diagram of MVC with V-C connection
図2-2: Controllerの表示が可能なMVCのコミュニケーション図(動的構造図)

図1との違いのポイントを挙げる。
  • ConcreteViewにControllerによる表示のためのI/Fがある
  • ConcreteControllerからConcreteViewへの関連がある
  • ControllerのViewのみの変更は、C-Vに閉じて完結される

この具象Controllerと具象Viewとの関連は必須ではない(全てのViewがControllerの表示を行う必要はない、CUIやリモート制御だとModelのViewがControllerのUIを表示しないこともある)ので、抽象Controllerと抽象Viewとの間には現れない。

C-V間の関連が無いMVCは、抽象レベルだけを取り上げた、MVCの一部のエッセンスだけを示したものである。それで済む時もあるが、それが最も美しいということではない。
ソフトウェアのデザインパターンをかじった人ならわかると思うが、抽象クラスだけで構成されるパターンは存在しない。というより、抽象クラスを含むパターンは、オブジェクト指向の「依存関係逆転の原則」の存在箇所の明確化のためにも、最低どれか1つの具象クラスが無いと成り立たない。具象クラスまで含めてのデザインパターンである。

ディスプレイに表示するViewがあって、UIがそのディスプレイ上に無いシステムは、MVCパターンとして考える意味が無い(何の為にViewを分離しているのかわからない)。MVCパターンは元々GUIのあるシステムを対象に含めているので、その要素を省いて語るべきではないと、筆者は考える。


"MODELS-VIEWS-CONTROLLERS"のControllerの定義には、他にもV-C間の具象レベルでの関連が示されている。

Conversely, a view should never know about user input, such as mouse operations and keystrokes. It should always be possible to write a method in a controller that sends messages to views which exactly reproduce any sequence of user commands.
(訳:同様に、全てのviewはマウス操作やキー入力といったユーザー入力には一切関知しない。ユーザーコマンド列を再生成するだけのviewにメッセージを送るmethodをControllerに書くことは可能なだけである。)
この文書には他に"user output"という表現もあって、"user input"と"messages"と"user commands"の違いがわかりにくい(はっきり言って、筆者にはわからない)が、"THING-MODEL-VIEW-EDITOR"のVIEWのEXAMPLE 1の所に
It understands a message asking it for an item that is positioned at a given point within its frame, and a message asking it to select a given item.
(筆者注:この文脈ではframeはControllerによる表示のこと。"a given point within its frame"と書くことにより、"user input"そのものではなく、抽象的な意味合いの位置情報であることを強調しているものと思われる)
One possible sequence for selection is that the Editor reacts to redbug and asks the ListView for the item that is pointed to. The Editor then asks the ListView and any other Views to select that item.
(筆者注:この文脈ではEditorは具象Controller、ListViewは具象Viewのこと)
とあるので、Controllerは、現在Viewがある場所に何を表示しているかを問い合わせることができる、という意味だと解釈するのが妥当であろう。マウス操作による画面上のクリックなど、ユーザーがView上の表示に依存する操作を行った場合、Viewがその位置に何を表示しているかがわからない限り、Controllerはユーザーの指示を解釈できないが、その問題を解決する為の必要最小限のサポートをViewが(あくまでユーザー入力の生データには関知せずに)行うべきだということである。

また、その少し後ろのEXAMPLE 4の所に、

In addition, it will need some operations on the View itself, they have to do with the positioning of the symbols in the diagram.
つまり、Modelの要素の表示位置を変えるなど、Modelの変更とは無関係にModelのViewが変化する場合は、そのためのI/F(呼び出すのはController)がViewに必要になるということである。

また、"MODELS-VIEWS-CONTROLLERS"に戻って、VIEWの定義に、次のような具象M-V間の関係が書かれている。

A view ... gets the data necessary for the presentation from the model by asking questions. It may also update the model by sending appropriate messages. All these questions and messages ...
つまり、ViewがModelを変更することもあり得るということである。これだけでは何のことかさっぱりわからないが、"THING-MODEL-VIEW-EDITOR"のVIEWの所の冒頭に
A View is also able to perform such operations upon the Model that is reasonabely associated with that View.
とあり、その後ろのEXAMPLE 6の所に
It is also able to pass on operations on the network and its activities that are related to this particular View. Typical operations have to do with modifying the current schedule.
(筆者注:ここではnetworkはModel、activitiesとscheduleはnetworkの要素)
とあるので、(Controllerを介して)Modelの要素に十分に直結したView上の変更が発生すれば、それに対応する変更を、Controllerに関係なく(Controllerを介さずに)、Viewが直接Modelに対して行っても良いということなのである。

これらを含め、MVCパターンは次のように図示できる。

Class diagram of MVC without V-C connection
図3-1: MVCのクラス図(静的構造図)

Communication diagram of MVC without V-C connection
図3-2: MVCのコミュニケーション図(図2-2からの差分のみ)

ところで、以前のエントリーに、J2EEやASP.NETなどがMVCを参考にしていると書いたが、これらで使われているのは元々のMVCパターンとは異なる、"JSP Model 2 architecture"または単に"Model 2"と呼ばれるアーキテクチャーである。
一応、Webサーバー側のMVCパターン実装、ということになっているが、基本的にはサーバー側はconnectionlessかつstatelessであり、Viewの出力はHTTP requestに対するresponseとしてユーザーに出力するため、Modelの状態が変化した時にViewが表示を更新する、ということができず、M-V間にObserverパターンの関係が無いのが特徴である。

Class diagram of "Model 2"
図4-1: "Model 2"のクラス図

Communication diagram of "Model 2"
図4-2: "Model 2"のコミュニケーション図

元々、"Model 2"が最初に現れた時にはMVCの用語は使われていなかったが、次第にMVCの用語を用いて説明されるようになった(下記参考リンク参照)。それにより、MVCと"Model 2"がごっちゃにされ、人々のMVCの定義がバラバラになり、MVCをややこしくした。
筆者は、ViewがObserverでないMVCはあり得ないと思うので、"Model 2"もMVCではないと思う(し、結構多くの人に賛同頂けるものだと信じている)が、特にWeb系ではそんなことを気にしない人も少なくないようである。
"Model 2"を含めると本当に話がややこしくなるので、このサイトでは"Model 2"はMVCパターンに含めない。

●"Model 2"の参考リンク
  • Understanding JSP Model 2 architecture - JavaWorld --- 現時点での事実上の原典
  • MVC, Model 2, Java WebApps (Brian's Waste of Time) --- "Then the Web happens and Sun starts talking about Model2 in terms of MVC."("Model 2"がMVCの用語を使って語られるようになり、Sunもそれに乗っかった)ということが書かれている。
  • Java EE 5のTutorialの中の1ページ --- Webアプリの世界ではMVCはModel-2と同じものだとみなされることがしばしばある、と書かれている。
    Note - When employed in a web application, the MVC architecture is often referred to as a Model-2 architecture. The bookstore example discussed in Chapter 4, Java Servlet Technology, which intermixes presentation and business logic, follows what is known as a Model-1 architecture. The Model-2 architecture is the recommended approach to designing web applications.
  • How Struts Implements Model 2 --- "The Origins of Model 1/Model 2"という章に、MVCとModel 2との関係が書かれている。
  • ASP.NET Presentation Patterns --- The original MVCと"Model2"と"ASP.NET MVC Framework"との関係が解説されている。