web-dev-qa-db-ja.com

本当にMVCとは何ですか?

真面目なプログラマーとして、どのように質問に答えますかMVCとは

私の考えでは、MVCは一種の曖昧なトピックです。そのため、視聴者が学習者であれば、論争の余地がないと思われる一般用語で自由に説明できます。

しかし、あなたが知識豊富な聴衆、特に面接担当者と話している場合、私は「まあそうではない!...」の反応を危険にさらすことのない方向を考えるのに苦労します。私たちは皆、実世界での経験が異なっており、同じMVC実装パターンに実際に2回会ったことはありません。

具体的には、厳密さ、コンポーネントの定義、部品の分離(どの部品がどこに適合するか)などに関して意見の相違があるようです。

それで、MVCをどのように説明する必要がありますか正しく、簡潔で、議論の余地のない方法で?

206
Nicole

MVCはソフトウェアアーキテクチャ(システムの構造)であり、ドメイン/アプリケーション/ビジネス(必要に応じて)ロジックを残りのユーザーインターフェイスから分離します。これは、アプリケーションを3つの部分(モデル、ビュー、コントローラー)に分離することによって行われます。

モデルは、アプリケーションの基本的な動作とデータを管理します。情報の要求に応答したり、情報の状態を変更する指示に応答したり、情報が変化したときにイベント駆動型システムのオブザーバーに通知したりすることもできます。これは、データベースでも、任意の数のデータ構造やストレージシステムでもかまいません。つまり、アプリケーションのデータとデータ管理です。

ビューは、アプリケーションのユーザーインターフェイス要素を効果的に提供します。モデルのデータを、ユーザーインターフェイスに適したフォームにレンダリングします。

コントローラはユーザー入力を受け取り、モデルオブジェクトとビューを呼び出して適切なアクションを実行します。

全体として、これら3つのコンポーネントは連携して、MVCの3つの基本コンポーネントを作成します。

158
Bob

アナロジー

お父さんにMVCを次のように説明しました:

MVC(モデル、ビュー、コントローラー)は、アプリケーションのコードを整理して保守性を向上させるためのパターンです。

スタジオでカメラを持つカメラマンを想像してみてください。顧客は彼に箱の写真を撮るように頼みました。

ボックスはモデル、写真家はコントローラー、カメラはビュー

ボックスはカメラや写真家についてを知らないため、完全に独立しています。この分離により、写真家はボックスの周りを歩き、カメラを任意の角度に向けて、希望するショット/ビューを取得できます。

非MVCアーキテクチャは緊密に統合される傾向があります。ボックス、コントローラ、カメラが同じオブジェクトである場合、ボックスを引き離してから、ボックスとカメラの両方を再構築する必要があります。新しいビューを取得したいたびに。また、写真を撮るのは、いつも自分撮りを撮ろうとするようなものです。


詳細説明

MVCを理解したように感じたのは、次のメールリストの質問/回答を読んだ後だけでした。引用: https://mail.python.org/pipermail/python-list/2006-January/394968.html

ブワハは書きました:

著者は、MVCデザインの例としてwxPythonのmvctree.pyを参照しています。しかし、私はまだ環境に配慮していないため、特定の例が複雑すぎて、著者が推奨している分離を理解できていません。

MVCはすべて、懸念の分離に関するものです。

モデルはプログラムのデータ(プライベートデータとクライアントデータの両方)の管理を担当します。ビュー/コントローラーは、プログラムのクライアントデータと対話する手段を外部に提供する責任があります。

モデルは、プログラムの他の部分がモデルと対話できるようにするための内部インターフェース(API)を提供します。ビュー/コントローラーは、外部インターフェース(GUI/CLI/Webフォーム/高レベルIPCなど)を提供し、プログラム外のすべてのものと通信できるようにします。

モデルは、プログラムのデータの整合性を維持する責任があります。破損した場合、すべての人にとってゲームオーバーになるからです。ビュー/コントローラーは、UIの整合性を維持し、すべてのテキストビューが最新の値を表示していること、現在のフォーカスに適用されないメニュー項目を無効にすることなどを担当します。

モデルにはビュー/コントローラーコードが含まれていません。 GUIウィジェットクラスも、ダイアログボックスのレイアウトやユーザー入力を受け取るコードもありません。ビュー/コントローラーにはモデルコードが含まれていません。 URLを検証したり、SQLクエリを実行したりするためのコードも、元の状態もありません。ウィジェットが保持するデータは表示のみを目的としており、モデルに保存されている実際のデータを反映したものです。

これが本当のMVC設計のテストです。ビュー/コントローラーが接続されていなくても、プログラムは本質的に完全に機能するはずです。 OK、外の世界はその形式でそれとやり取りするのに問題がありますが、適切なModel APIの呪文を知っている限り、プログラムは通常どおりにデータを保持して操作します。

なぜこれが可能ですか?まあ、簡単な答えは、それはすべて、モデルレイヤーとビュー/コントローラーレイヤーの間の結合が低いおかげです。しかし、これは完全な話ではありません。 MVCパターン全体の鍵は、これらの接続が行われる方向です。すべての命令フローfromビュー/コントローラーtoモデル。モデルはビュー/コントローラーに何をすべきかを決して指示しません。

どうして? MVCでは、ビュー/コントローラーはモデル(特に、モデルのAPI)について少し知っていることが許可されていますが、モデルはビュー/コントローラーについて何も知ることができません。

どうして? MVCは懸念事項を明確に分離するためのものです。

どうして?プログラムの複雑さが制御不能になり、開発者であるあなたをその下に埋めるのを防ぐため。プログラムが大きくなるほど、そのプログラムのコンポーネントの数が増えます。そして、それらのコンポーネント間に存在する接続が多いほど、開発者が個々のコンポーネントを維持/拡張/交換したり、システム全体がどのように機能するかを追跡することが難しくなります。これについて自問してみてください。プログラムの構造の図を見るとき、木や猫のゆりかごを見たほうがいいですか。 MVCパターンは、循環接続を禁止することで後者を回避します。BはAに接続できますが、AはBに接続できません。この場合、Aはモデルで、Bはビュー/コントローラーです。

ところで、あなたが鋭い場合は、先ほど説明した「一方向」の制限の問題に気付くでしょう:モデルが許可されていない場合に、モデルがユーザーのデータの変更をビュー/コントローラーに通知する方法ビュー/コントローラーにメッセージを送信してもかまいません。しかし、心配しないでください。これには解決策があり、最初は少し迂回しているように見えても、かなりきちんとしています。すぐに戻ってきます。

実際には、ビュー/コントローラオブジェクトは、モデルのAPIを介して、1。モデルに処理を実行するように指示(コマンドを実行)、2。モデルに処理を実行するように指示(データを返す)できます。ビュー/コントローラーレイヤーは、モデルレイヤーに指示をプッシュし、モデルレイヤーから情報をプルします

そして、最初のMyCoolListControlの例がうまくいかないのは、そのクラスのAPIがその情報をpushedする必要があるためです。これにより、レイヤー間の双方向のカップリングに戻ります。 、MVCルールに違反し、あなたが[おそらく]そもそも避けようとしていた猫のゆりかごのアーキテクチャに戻ってしまう。

代わりに、MyCoolListControlクラスはフローを使用して、必要なときに必要なデータを下のレイヤーから取得する必要があります。リストウィジェットの場合、それは通常、存在する値の数を尋ね、次にそれらの各項目を順番に尋ねることを意味します。これは、それを行うための最も単純で最も緩い方法であり、したがって、結合を最小限に抑えるためです。そして、ウィジェットが、たとえば、これらの値をニースのアルファベット順にユーザーに提示したい場合は、それが許容範囲です。そしてもちろんその責任。

さて、先にほのめかしたように、MVCベースのシステムでUIの表示をモデルの状態と同期させるにはどうすればよいですか?

ここに問題があります:多くのViewオブジェクトはステートフルです。チェックボックスはチェックされている場合とチェックされていない場合があります。テキストフィールドには編集可能なテキストが含まれている場合があります。ただし、MVCではすべてのユーザーデータがモデルレイヤーに保存されることを規定しているため、他のレイヤーが表示目的で保持しているデータ(チェックボックスの状態、テキストフィールドの現在のテキスト)は、そのプライマリモデルデータの補助コピーである必要があります。ただし、モデルの状態が変化すると、その状態のビューのコピーは正確でなくなり、更新する必要があります。

しかし、どうやって? MVCパターンは、モデルがその情報の新しいコピーをビューレイヤーにプッシュするのを防ぎます。いや、モデルがビューにメッセージを送信して、状態が変化したことを伝えることさえできません。

よくほとんど。モデルレイヤーが他のレイヤーと直接通信することは許可されていません。これを行うには、モデルレイヤーがそれらのレイヤーについて何かを知っている必要があり、MVCルールがそれを防ぐためです。しかし、木が森に落ちて、周りに誰もそれを聞くことができない場合、それは音を立てますか?

答えは、あなたが知っているように、通知システムをセットアップすることです。特に、興味深いことをしたことを誰にも通知できない場所をモデルレイヤーに提供します。他のレイヤーは、その通知システムを使用してリスナーをポストし、実際に関心のあるアナウンスをリッスンできます。モデルレイヤーは、誰が聞いているのか(または誰かがまったく聞いている場合でも)知る必要はありません。アナウンスを投稿しただけで、それを忘れてしまいます。そして、誰かがそのアナウンスを聞いて後で何かをしたいと思った場合-モデルに画面上の表示を更新できるように新しいデータを要求するような場合-素晴らしいです。モデルは、API定義の一部として送信する通知をリストするだけです。そして、誰もがその知識で何をするかは彼ら次第です。

MVCは維持され、誰もが幸せです。アプリケーションフレームワークは組み込み通知システムを提供しているかもしれませんし、そうでない場合は独自に作成することもできます(「オブザーバーパターン」を参照)。

...

とにかく、それが役立つことを願っています。 MVCの背後にある動機を理解すると、一見したところ、必要以上に複雑に見えたとしても、物事が実際に行われている方法が理にかなっている理由がわかり始めます。

乾杯、

持っている

138
JW01

MVCはほとんどが流行語です

かつてはパターンと考えられていましたが、1979年の元の定義は、だまされ、受け継がれ、誤解され、元のコンテキストから外されています。それは宗教に似ているようになるまでは不明確に定義されており、これは確かにその貨物信仰者がそれを守るのに役立ちますが、その名前はしっかりしたガイドラインのセットに関連付けられなくなりました 。そのため、もはやパターンと見なすことはできません。

MVCは、Webアプリケーションを説明するためのものではありませんでした。
最新のオペレーティングシステムでも言語でもありません。
(1979年の定義を実際に冗長にした人もいます)

に作られました。そしてそれはうまくいきませんでした。

卑劣なweb-mvcハイブリッドを扱います。これは、そのひどい流行語のステータス、不適切な定義、およびsemi-illiterate-programmersターゲットの人口統計として、ソフトウェアパターン一般に本当に悪い宣伝をします。

したがって、MVCは心配についての分離になり、それについてあまり考えたくない人のために蒸留されました。

  • dataモデルは一方向で処理され、
  • 別のview
  • 残りは "controller"という名前で、読者の裁量に任されています。

90年代のWebサイト/ Webアプリケーションは、懸念の分離を適用するために実際に使用しませんでした。

それらは混在したスパゲッティコードの恐ろしいボットでした。
UIの変更、再設計、およびデータの再配置は、信じられないほど難しく、費用がかかり、長く、憂鬱で、不運でした。

ASP、JSP、およびPHPのようにWebテクノロジーを使用すると、簡単に混合できますデータに関する懸念事項とアプリケーションの懸念事項を表示します。この分野の初心者は通常、昔のような複雑なコードの泥だらけ。

したがって、サポートフォーラムの無限ループで「use MVC」を繰り返す人が増えています。マネージャーやマーケティング担当者を含むほどに人数が増え(一部の用語は、パターンが意味をなすGUIプログラミングの時代からすでによく知られていました)、今、私たちが直面する流行語の巨大なものになりました。

現状では、常識であり、方法論ではありません。
これは開始点であり、解決策ではありません。
それは人々に呼吸する空気、またはクランチを作るように言うようなものです、ではないがんの治療法

87
ZJR

それを定義する最良の方法は、それを発明した Trygve Reenskaug のオリジナルの文章に行くことです: http://heim.ifi.uio.no/~trygver/themes/mvc /mvc-index.html

特に、このペーパーは一般に定義テキストと見なされます。 http://heim.ifi.uio.no/~trygver/1979/mvc-2/1979-12-MVC.pdf

モデル

モデルは知識を表します。モデルは単一のオブジェクト(むしろ面白くない)の場合もあれば、オブジェクトの何らかの構造の場合もあります...

一方のモデルとそのパーツ、および他方のモデルの所有者が認識している表現された世界の間には、1対1の対応があるはずです。したがって、モデルのノードは、問題の特定可能な部分を表す必要があります。

モデルのノードはすべて同じ問題レベルにある必要があります。問題指向のノード(カレンダーの予定など)と実装の詳細(段落など)を混在させるのは混乱し、不適切なフォームと見なされます。

VIEWS

ビューは、そのモデルの(視覚的な)表現です。通常、モデルの特定の属性を強調表示し、他の属性を抑制します。したがって、これはプレゼンテーションフィルターとして機能します。

ビューはそのモデル(またはモデルパーツ)にアタッチされ、質問することでモデルからプレゼンテーションに必要なデータを取得します。また、適切なメッセージを送信してモデルを更新する場合もあります。これらすべての質問とメッセージはモデルの用語に含まれている必要があるため、ビューはそれが表すモデルの属性のセマンティクスを知る必要があります。 (たとえば、モデルの識別子を要求し、Textのインスタンスを期待する場合があります。モデルがTextクラスであるとは限りません。)

コントローラー

コントローラは、ユーザーとシステム間のリンクです。画面上の適切な場所に表示されるように関連するビューを構成することにより、ユーザーに入力を提供します。これは、メニューやコマンドやデータを提供するその他の手段をユーザーに提示することにより、ユーザー出力の手段を提供します。コントローラーはそのようなユーザー出力を受け取り、それを適切なメッセージに変換し、これらのメッセージを1つ以上のビューに渡します。

コントローラはビ​​ューを補完するべきではありません。たとえば、ノード間にビューに矢印を描画してノードのビューを接続するべきではありません。

逆に、ビューは、マウス操作やキーストロークなどのユーザー入力を認識してはなりません。ユーザーコマンドのシーケンスを正確に再現するビューにメッセージを送信するメソッドをコントローラーに記述することは常に可能である必要があります。

エディター

コントローラーはそのすべてのビューに接続されており、コントローラーのパーツと呼ばれます。一部のビューは、ユーザーがビューによって提示される情報を変更できるようにする特別なコントローラー、editorを提供します。このようなエディターは、コントローラーとそのビューの間のパスにスプライスされる場合があり、コントローラーの拡張として機能します。編集プロセスが完了すると、エディターはパスから削除され、破棄されます。

エディターは接続されたビューのメタファーを介してユーザーと通信するため、エディターはビューと密接に関連付けられていることに注意してください。コントローラーはビューを要求することでエディターを手に入れます-他に適切なソースはありません。

39
Larry OBrien

MVCは、ビジネスロジックをプレゼンテーションから分離するために使用されるデザインパターンです。

他の多くのデザインパターンとは異なり、通常は簡潔に実装されていませんが、フレームワークのベースとなっています。

Strategyパターンを実装するアプリケーションはそれについてのほんの一部ですが、WebアプリがMVC設計パターンを使用していると言うことは、そのアーキテクチャを非常に定義していることです

11
Boris Yankov

MVCは、システムまたはサブシステムの以下のコンポーネントを分離するソフトウェア設計です。

  1. モデル-アプリケーションまたはそのコンポーネントの状態に関するデータ。変更またはアクセスのためのルーチンが含まれる場合があります。
  2. 表示-データ(モデル)の解釈。これは視覚的表現に限定されますが、音声、派生情報(別のモデルオブジェクトにパイプされた統計など)の場合もあります。さらに、1つのモデルに複数のビューが含まれる場合もあります。
  3. コントロール-モデルの変更を呼び出すシステムへの外部入力を処理します。コントロール/ビューは密接に関連している場合があります(UIの場合)。ただし、他の外部入力(ネットワークコマンドなど)は、ビューとは完全に独立して処理されます。
8
lorean

MVCは概念または類似パターンのファミリーであると私は思います。

この記事は読む価値があると思います。 Martin FowlerによるGUIアーキテクチャ

6
franziga

まず、質問の質問者が誰で、どのような答えを探しているのかを判断する必要があります。この質問には、「どういう意味ですか?」などの別の質問で答えます。

彼らが一般的にMVCを参照しているかどうか、MVCの特定の実装(つまり、asp.net MVC、Spring MVC、Smalltalk MVCなど)を参照しているかどうか、技術的に、哲学的に(はい、それは哲学も)など。

これがテストに関する質問であり、質問者に明確にするように依頼できない場合は、コンテキストに基づいて推測する必要があります。

良い、簡単な答えは次のとおりです。

MVCは、ソフトウェアのユーザーインターフェイスアーキテクチャであり、より保守しやすいソフトウェアを容易にするために、構造的な問題と動作上の問題を分離するために使用されます。

次のように言うこともできます:

モデルとコントローラーのビューを分離することで、コンポーネントの責任に基づいたコンポーネントの分離が促進されます。理論的には、そして実際には通常、これは、システムのさまざまな部分が混ざり合い、より複雑なシステムを作成するのを防ぐことにより、保守性の向上に役立ちます。

しかし、最終的には、彼らが期待している回答を与えるかどうかで判断されます。問題の唯一の解決策は、彼らが期待している答えの種類を見つけることです。

3

これについて私が言いたいのはこれです。私が最もよく知っていることであり、モバイルアプリケーションを始める前に完全に理解していないため、モバイルアプリケーションの観点から説明しようと思います。
たとえば、Androidとしましょう。
プレゼンテーションレイヤー、つまりユーザーインターフェイスは完全にxmlで指定できます(ほとんどの場合そうです)。簡単にするために、1つのxmlファイルがアプリケーションの1つの画面を記述しているとしましょう。 XMLファイルは、コントロール、コントロールのレイアウト、配置、色、サイズ、文字列ラベルなど、プレゼンテーションに関するすべてを指定します。しかし、いつ呼び出され、いつ画面に配置されるかについては何も知りません。スタンドアロンレイアウトですか、それとも一部の大きなレイアウトの一部ですか?完璧です[〜#〜] view [〜#〜]

さて、ビューは明らかにどこかの時点で画面上に配置する必要があるので、どうすればよいでしょうか?あなたの[〜#〜] controller [〜#〜]、in AndroidはActivityと呼ばれます。名前が示すように、アクティビティはいくつかのアクティビティを行います。その唯一の目的がステップ1で定義されたビューを表示するには、アクションを実行します。したがって、アクティビティはビューをフェッチして画面に表示します。ビューはアクティビティについて何も知らないので、同様にアクティビティは実際のプレゼンテーションについて何も知りません。私たち(プログラマー)はアクティビティのコードを1行も変更せずに、ビューのレイアウトを複数回再配置します。

さて、実際に何もせずに、ニースの光沢のある明確に定義されたxmlレイアウトを提示することはあまり役に立ちません。ユーザーが入力したデータを保存したいとしましょう。アクティビティは、ユーザーからのデータの取得から、それを処理するために他の誰かに渡す(処理、保存、削除)まで、このプロセスに取り組む必要があります。誰に渡るの?さて、[〜#〜]モデル[〜#〜]へ。私は、モデルが存在するアプリケーションコンテキストについて何も知らない純粋な。Javaクラスとしてモデルを考えるのが好きです(実際には、場合)。

名前、住所、年齢の3つのプロパティを持つPersonクラスがあるとします。 XMLで定義されたレイアウトには、ユーザー入力用の3つのフィールド(名前、住所、年齢)があります。私のアクティビティは、ユーザー入力から3つの値を取得し、新しいPersonオブジェクトを作成して、Person固有のロジックを処理する方法を知っているメソッドを呼び出します。そこにあります。モデルビューコントローラー。

2
Maggie

私はいつも、パターンが新しいものではなく、何年も前から存在していることを伝えることから始めます...この時点で、彼らは私に好奇心旺盛な外観とBAMを与えます!、彼らは夢中になっています:

そして、私は以前の回答のようなさまざまな点についてほとんど話しますが、JB Kingが言ったように、ASP.NET MVCなど、文脈にも注意することが重要だと思います。

1
Dal