MVCの「C」は本当に必要ですか?


38

Model-View-Controllerパターンでのモデルとビューの役割は理解していますが、コントローラーが必要な理由を理解するのに苦労しています。

MVCアプローチを使用してチェスプログラムを作成していると仮定しましょう。ゲームの状態がモデルになり、GUIがビューになります。この場合、コントローラーは正確に何ですか?

これは、たとえばタイルをクリックしたときに呼び出されるすべての関数を備えた単なる別のクラスですか?ビュー自体でモデルのすべてのロジックを実行しないのはなぜですか?


1
個人的には、これが私がしていることですMVCに代わるものがない場合もありますが、私はそれに耐えられません。
マイクダンラベイ

10
3つの単語...「懸念の分離」。
トラビスJ

4
.net以前のほとんどすべてのWindowsプログラムは、コントローラーなしでDoc-Viewを使用していました。これは比較的成功しているようです。
マーティンベケット

マーティン、変更不可能なモノライト。
独立

以下で回答しましたが、追加します。はい、明確なコントローラークラスなしでアプリケーションを構築できますが、それはMVCではありません。「MVCアプローチ」を想定しているので、はい、コントローラーが重要な役割を果たします。MVCではないパラダイムを選択した場合、コントローラーがない可能性が十分にあります。
カレブ

回答:


4

あなたの例を使用すると、コントローラーが合法的な動きであるかどうかを決定します。コントローラーは、モデルから受け取った情報を使用して、起動時にボード上のピースを配置する方法をビューに知らせます。コントローラーで処理できるものは他にもありますが、重要なのはそのレイヤーのビジネスロジックについて考えることです。

コントローラーが行うことは、サインアップページのように情報をやり取りすることだけです。また、コントローラーを開発の難しい部分とする場合もあります。たとえば、ルールを適用したり、複雑な数学を実行したりするなど、そのレイヤーで行う必要のあることがたくさんあるためです。コントローラーを忘れないでください!


36
「あなたの例を使用すると、コントローラーが合法的な動きであるかどうかを決定します」。これは悪い例です:(そのようなロジックはモデルにもあります。そうでなければ、ロジックはコントローラーとモデルの間で分割されます
。-ダイム

6
@Dime-モデルにはロジックを一切含めないでください。コントローラーは、ロジックを保持しているため、「制御」します。
トラビスJ

34
@TravisJそこにはまったく同意しないでください。コントロールすることは、仕事をする方法を知ることを意味しません。行うオブジェクトを制御することです。したがって、作業を行うためのロジックがモデルになりますと、コントローラは、コントローラブロットのためのレシピ...だろう私の見解では、コントローラになどあまりにも多くのロジックアクションの必要な要件を実行するために使用するモデルを制御します
dreza

25
OOPの重要なポイントは、まとまりのあるデータと動作をまとめて保持し、状態を内部的にカプセル化することです。「モデル」は、動作とデータの両方をモデル化します。
ミスコ

12
-1コントローラーにビジネスロジックを含めることはできません。モデル「アプリ」であり、データを保持し、アプリで発生する可能性のあるすべての呼び出し可能なルーチンを備えています。必ずしもすべてが1つのファイルまたはクラスにあるとは限りません。ビューは、モデルの状態を視覚化します。コントローラーは、モデル/ビューと実世界/入力の橋渡しをします。アプリをWebアプリとして「公開」したいですか?HTTPと適切なHTMLベースのビューを処理するコントローラーが必要です。アプリへのコマンドラインインターフェイスが必要ですか?適切なコントローラーとビューが必要です。これらの場合、モデル、ビジネスロジックは変更されません。
22:34にdeceze

39

ビュー自体でモデルのすべてのロジックを実行しないのはなぜですか?

コントローラーは、モデルとビューを結合する接着剤であり、モデルとビューを分離する断熱材でもあります。モデルはビューについて何も知らないはずであり、逆もまた同様です(少なくともAppleのMVCバージョンでは)。コントローラーは双方向アダプターのように機能し、ビューからのユーザーアクションをモデルへのメッセージに変換し、モデルのデータを使用してビューを構成します。

コントローラーを使用してモデルとビューを分離すると、コードの再利用性、テスト性、柔軟性が向上します。チェスの例を考えてみましょう。モデルにはもちろんゲームの状態が含まれますが、動きが合法であるかどうかを判断したり、ゲームが終了したときに決定したりするなど、ゲームの状態の変更に影響するロジックも含まれます。ビューにはチェス盤と駒が表示され、駒が動くとメッセージが送信されますが、駒の背後にある意味、各駒がどのように動くかなどについては何も知りません。コントローラーはモデルとビューの両方を知っていますプログラムの全体的な流れ。ユーザーが「新しいゲーム」ボタンを押すと、ゲームを作成するようモデルに指示し、新しいゲームの状態を使用してボードをセットアップするコントローラーです。ユーザーが移動した場合、

モデルとビューを別々にしておくことで得られるものを見てください:

  • 他のモデルまたはビューを変更せずに変更できます。いずれかを変更するときにコントローラーの更新が必要になる場合がありますが、これはある意味で利点の一部です。変更される可能性が最も高いプログラムの部分はコントローラーに集中しています。

  • モデルとビューの両方を再利用できます。たとえば、有名なゲームを説明するためのモデルとしてRSSフィードと同じチェスボードビューを使用できます。または、同じモデルを使用して、ビューをWebベースのインターフェイスに置き換えることもできます。

  • モデルとビューの両方のテストを簡単に作成して、それらが期待どおりに機能することを確認します。

  • 多くの場合、モデルとビューの両方が標準パーツを利用できます。配列、マップ、セット、文字列、およびモデルの他のデータコンテナー。ビューのボタン、コントロール、テキストフィールド、画像ビュー、テーブルなど。


1
デスクトップアプリケーションの元のMVCアーキテクチャでは、ビューはアクティブなクラスであり、モデルを直接監視し、コントローラーから切断されていました。
ケビンクライン

すべての答えの問題は、人々が投稿するのと同じくらい多くのMVCの解釈があるということです。また、上記の利点は、MVCの特定の解釈にのみ適用されます。ほとんどのロジックをコントローラー(またはモデル)に配置し、コントローラーでView呼び出し/特定のメソッド呼び出しを開始すると、コントローラー/モデルコンボがスタンドアロンで非常に再利用可能になります。ほとんどの場合、必要なのは新しいビューです。ビューを再利用する必要はありませんでした。RSSの例でさえ、古いビューを使用し、その間にRSSレイヤーを配置した新しいビューで簡単に処理できます。
ダンク

2
@Dunk:ビジネスロジックを直接テストできるように、ビジネスロジックをユーザーインターフェイスから分離することが重要です。
ケビンクライン

@Kevin:私は完全に同意します。ビジネスロジックはユーザーインターフェイスに属していません。ただし、コントローラーはユーザーインターフェイスの一部である必要はありません。多くの定義があるということです。ある人の定義では、コントローラーはボタンの押下を処理し、別の人はそれをビューの一部として配置します。ビューがオペレーターのアクション(ボタンの押下/要素の選択)をアプリケーションリクエストに変換する方法を知っている場合、コントローラー/モデルは、GUI、コンソール、ネットワークインターフェースなど、ほぼすべての種類のユーザーインターフェースで非常に再利用可能になります。
ダンク

1
@Dunk:「コントローラー」のようなものなら何でも呼び出すことができると思いますが、MVCアーキテクチャーではコントローラーはユーザーインターフェイスに依存しているため、ユーザーインターフェイスの一部です。
ケビンクライン

7

この一般的な設計パターンを実装する方法は多数ありますが、基本的な考え方は、必要に応じてさまざまな懸念を分離することです。MVCは、次の意味で優れた抽象化です。

Model:そのデータを表し、それが意味するものは何でも
View:ユーザーインターフェイスを表し、それが意味するものは何でも
Controller:そのモデルとビューを相互作用させる接着剤を表します

全体を指定しないため、非常に柔軟です。多くの人々は、各要素が何を意味するのか、これらの代わりにどの名前を使用するべきか、実際に3つまたは2つまたは4つまたは5つのコンポーネントが存在するかどうかの詳細を議論する多くの帯域幅を無駄にしていますが、それはポイントを失っていますある程度。

アイデアは、ロジックの異なる「チャンク」を分離して、重複しないようにすることです。プレゼンテーションをまとめ、データをまとめ、ロジックをまとめ、コミュニケーションをまとめます。などなど。ある程度、これらの関心領域が重ならないほど、それらで興味深いことをするのが簡単になります。

本当に心配する必要があるのはこれだけです。


3
接着剤、接着剤、私はその定義が好きです、それはとても正しいです:モデル全体がMVG名付けられるべきであり、人々は見つけるもののない優雅さを求めて頭を掻くのを止めます。
ZJR

1
「接着剤」の場合は+1。また、スクリプト言語で行われるのに最適な部分であることも意味します(それらは接着に優れている傾向があります)。
ドナルフェローズ

@DonalFellows私はそれがとても好きでした。一緒に「接着剤」2つの異種のエンティティは弱い型付けのスクリプト言語(つまり、JavaScriptが)促進多くの柔軟性を必要としていることを何か
ザックMacomber

4

これまでのところ、すべての良い答え。私の2セントは、コントローラーを何とどこのような質問で主に構築されていると考えるのが好きだということです。

  • チェスの駒(ビュー)をxに移動できるかどうかを尋ねられました。それは
    許可されていますか?よくわかりませんが、どこで誰に尋ねればよいか(モデル)は知っています。
  • データの保存を求められました。一体どうやってやるの?私はどこに尋ねればいいのか知っています!データの保存方法、または保存先はわかりませんが、Repositoryクラスは知っている必要があります。私はそれを転送し、それに対処させます。
  • モデルの移動先のユーザーに現在のチェスの駒の位置を表示する必要があります。作品を緑と黄色のどちらで表示するかわからない場合 気にするバー、これを処理できるビューがあることを知っているので、データをemに渡し、彼らはそれがどのように表示されるかを決めることができます。

これらの小さなスニペットは、MVCが伝えようとしている抽象化と概念を私がどのように思い出そうとしているかの例です。私の3つの主な思考プロセスは、何、どこ、どのようにですか。

内容と場所=>コントローラ方法と時期=>モデルとビュー

本質的に、私のコントローラーのアクションは小さくてコンパクトである傾向があり、それらを読むとき、時間の無駄のように見える傾向があります。綿密な調査では、彼らは信号機として機能し、さまざまな要求を適切な労働者に送りますが、実際の作業は一切行いません。


2

コントローラーは、ビューとモデルの両方のインターフェースを抽象化して、お互いを直接知る必要がないようにするのに役立ちます。オブジェクトの知識が少なくなればなるほど、よりポータブルで単体テストが可能になります。

たとえば、モデルは1つのコントローラーを介してそれ自体の別のインスタンスを再生できます。または、ネットワーク化されたコントローラーは、2人のプレーヤーのビューオブジェクトを一緒に接続できます。または、誰も知らないチューリングテストかもしれません。


2

イベントハンドラーを処理するときに実際に機能しますが、ビューとモデル間の相互作用を処理するコントローラーが必要です。ビューがモデルについて何も知らないようにすることが理想的です。それについて考えてください。jspですべてのデータベース呼び出しを直接行いたいですか?(ログインルックアップのような場合を除きます。)ビューがデータをレンダリングし、ビューレンダリングロジックではなく、ビジネスロジック自体を持たない限り、ビジネスロジックを持たないようにします。

GWTでは、MVPでよりクリーンな分離を実現します。ビューにビジネスロジックはまったくありません(正しく行われている場合)。プレゼンターはコントローラーとして機能し、ビューにはモデルに関する知識がありません。モデルデータは、単にビューに渡されます。


1

ドキュメントビュー(モデルビュー)は、MFCで記述された大半のWindowsアプリの標準モデルであるため、多くの場合に機能する必要があります。


1

Model-View-Controllerパターンでのモデルとビューの役割は理解していますが、コントローラーが必要な理由を理解するのに苦労しています。

(少なくとも最初に説明したように)モデルのポイントはドメインモデルになることです。ビューは、ドメインモデルをユーザーに表示することになっています。コントローラーは、低レベルの入力を高レベルのモデルの話にマッピングすることになっています。私の知る限り、理由は次のようなものです:A)SRPの高レベルの使用。B)モデルはアプリの重要な部分であると考えられていたため、重要ではなく、より速く変化するものを排除します。C)簡単にテスト可能な(およびスクリプト化可能な)ビジネスロジック。

盲人がチェスプログラムを使用できるようにしたい場合は、ビューを可聴バージョンとキーボードで動作するコントローラーに交換します。メールでゲームを追加する場合、テキストを受け入れるコントローラーを追加します。ゲームのネットバージョン?ソケットからコマンドを受け取るコントローラーがジョブを実行します。素敵な3Dレンダリングを追加します。クールな新しいビューです。ゼロモデル変更に必要なチェスはまだチェスです。

入力とモデル表現を混ぜると、その機能を失います。突然、チェスはチェスではなく、キーボードまたはネットワーク接続のチェスとは異なるマウスのチェスです。


0

MVCは馬鹿げていると思う。特定の分野ではうまく機能しているかもしれないが、個人的に私が書いたウェブサイトでさえmvcには向いていない。フロントエンド、バックエンドを聞いて、データベースエンドまたは他のエンドエンドではない理由があります

IMOにはAPI(バックエンド)とAPIを使用するアプリ(フロントエンド)が必要です。GETリクエストをコントローラー(単にバックエンドAPIを呼び出す)とhtmlを呼び出してビューを呼び出すことができますが、通常、ビューが純粋なhtmlまたはモデルとしてバックエンドAPIであるという話を聞くことはありません。

IMOすべてが堅牢なAPIである必要があります。実際、それらは(クリーンでよく構築されているように)堅固である必要はありませんが、その内部はプライベートのままである必要があり、APIのアプリ/フロントエンド/外部は決してデータベース接続を要求したり、生のクエリを実行したりすることはありません

コード/デザインに接着剤が含まれている場合、これで問題ありません。チェスゲームでGUIのスキンを編集できるマークアップがある場合、GUIは座標/入力を収集し、MovePiece(srcPosition、dstPostion)を呼び出します(有効な移動であるかどうかを示すブールまたは列挙型を返すことがあります) )そして、すべてのロジックがモデル内にあることを確認したら、必ずMVCと呼びます。しかし、私はまだクラスとAPIによって物事を整理し、すべてに触れるキッチンシンククラスがないことを確認します(すべてのことを知る必要があるAPIもありません)。


あなたの意見を歓迎しますが、この答えはOPの質問に対処しようとはしていません。
カレブ

0

静的なWebページを表示するブラウザーを考えてください。モデルはHTMLです。ビューは、画面上の実際の結果です。

JavaScriptを追加します。それがコントローラーです。ユーザーがボタンをクリックするか、イベントがJavaScriptに送信されるものをドラッグすると、何をするかを決定し、基になるHTML(モデル)を変更し、ブラウザー/レンダラーはそれらの変更を画面(表示)に表示します。

おそらく、別のボタンがクリックされ、イベントが何らかのハンドラー(コントローラー)に送信され、さらにデータをWebサービスに送信する要求が発生する可能性があります。次に、結果がHTML(モデル)に追加されます。

コントローラーはイベントに応答し、モデル内にあるもの、したがって画面/ビューにあるものを制御します。

少し前に戻ると、ブラウザー全体をビュー、サーバーをコントローラー、データをモデルと考えることができます。ユーザーがブラウザー(サーバー)に送信したイベント(コントローラー)のボタンをクリックすると、リソースがHTMLページ(モデル)として収集され、ブラウザーに戻されて表示されます(表示)

asp、php、javaのいずれのサーバーでも、「コード」(コントローラー)はクリックイベントを受信し、データベースまたはドキュメントリポジトリ(モデル)を照会し、HTMLを作成します。サーバーの観点から見ると、そのすべてのアクションの結果は、基礎となるデータストア(モデル)のビュー(HTML)です。しかし、クライアントの観点から見ると、サーバーへのリクエストの結果はそのモデル(HTML)です。

HTMLでJavaScriptをごちゃごちゃにしたり、モデル、ビュー、HTMLでPHPをごちゃごちゃにしたりしても、コントローラーは存在します。サーバーへのリクエストとサーバーからの応答を単純な双方向道路と考えても、モデル、ビュー、コントローラーがあります。


-2

私の経験では、従来のデスクトップmvc guiプログラムでは、コントローラーはビューにスパゲッティになってしまいます。ほとんどの人は、コントローラークラスを除外するのに時間をかけません。

ギャングオブフォーの本はこう言います:

Smalltalk MVCのデザインパターン

モデル/ビュー/コントローラー(MVC)の3つのクラス[KP88]は、Smalltalk-80でユーザーインターフェイスを構築するために使用されます。MVC内のデザインパターンを見ると、「パターン」という用語の意味がわかります。

MVCは3種類のオブジェクトで構成されています。モデルはアプリケーションオブジェクト、ビューはその画面表示、コントローラーはユーザーインターフェイスがユーザー入力に反応する方法を定義します。MVC以前は、ユーザーインターフェイスのデザインはこれらのオブジェクトをまとめてまとめていました。MVCはそれらを分離して柔軟性と再利用性を高めます。

MVCは、サブスクライブ/通知プロトコルを確立することにより、ビューとモデルを分離します。ビューは、その外観がモデルの状態を反映していることを確認する必要があります。モデルのデータが変更されるたびに、モデルはそれに依存するビューに通知します。それに応じて、各ビューはそれ自体を更新する機会を得ます。このアプローチでは、複数のビューをモデルに添付して、異なるプレゼンテーションを提供できます。モデルを書き換えることなく、モデルの新しいビューを作成することもできます。

次の図は、モデルと3つのビューを示しています。(簡単にするためにコントローラーは省略しました。)モデルにはいくつかのデータ値が含まれており、スプレッドシート、ヒストグラム、および円グラフを定義するビューはこれらのデータをさまざまな方法で表示します。モデルは、値が変更されるとビューと通信し、ビューはモデルと通信してこれらの値にアクセスします。

この例は、額面どおりに、モデルからビューを切り離す設計を反映しています。しかし、この設計はより一般的な問題にも適用できます。オブジェクトを切り離すと、あるオブジェクトへの変更が他のオブジェクトの詳細を知ることなく、他のオブジェクトに影響を与える可能性があります。このより一般的な設計は、Observer(293ページ)の設計パターンで説明されています。

MVCのもう1つの機能は、ビューをネストできることです。たとえば、ボタンのコントロールパネルは、ネストされたボタンビューを含む複雑なビューとして実装できます。オブジェクトインスペクターのユーザーインターフェイスは、デバッガーで再利用できるネストされたビューで構成できます。MVCは、ViewのサブクラスであるCompositeViewクラスでネストされたビューをサポートします。CompositeViewオブジェクトは、Viewオブジェクトと同じように機能します。コンポジットビューは、ビューを使用できる場所であればどこでも使用できますが、ネストされたビューを含んで管理します。

繰り返しますが、これは、コンポーネントの1つを扱うのと同じように、複合ビューを扱うことができる設計と考えることができます。しかし、この設計はより一般的な問題に適用できます。これは、オブジェクトをグループ化し、グループを個々のオブジェクトのように扱う場合に発生します。このより一般的な設計は、Composite(163)設計パターンで説明されています。一部のサブクラスがプリミティブオブジェクト(例:Button)を定義し、他のクラスがプリミティブをより複雑なオブジェクトにアセンブルする複合オブジェクト(CompositeView)を定義するクラス階層を作成できます。

MVCでは、視覚的な表示を変更せずに、ビューがユーザー入力に応答する方法を変更することもできます。たとえば、キーボードへの応答方法を変更したり、コマンドキーの代わりにポップアップメニューを使用したりできます。MVCは、応答メカニズムをControllerオブジェクトにカプセル化します。コントローラーのクラス階層があり、既存のコントローラーのバリエーションとして新しいコントローラーを簡単に作成できます。

ビューはControllerサブクラスのインスタンスを使用して、特定の応答戦略を実装します。別の戦略を実装するには、インスタンスを別の種類のコントローラーに置き換えるだけです。実行時にビューのコントローラーを変更して、ビューがユーザー入力に応答する方法を変更できるようにすることも可能です。たとえば、ビューを無効にして、入力イベントを無視するコントローラーを与えるだけで入力を受け入れないようにすることができます。

View-Controllerの関係は、Strategy(315)デザインパターンの例です。戦略は、アルゴリズムを表すオブジェクトです。アルゴリズムを静的または動的に置き換える場合、アルゴリズムのバリアントが多数ある場合、またはアルゴリズムにカプセル化する複雑なデータ構造がある場合に役立ちます。

MVCは、ファクトリメソッド(107)などの他のデザインパターンを使用して、ビューのデフォルトコントローラークラスを指定し、デコレーター(175)を使用してビューにスクロールを追加します。しかし、MVCの主な関係は、Observer、Composite、およびStrategyデザインパターンによって与えられます。


1
この投稿全体から最初の2つの段落を引いたものは、Design Patternsから逐語的に取られているようです。読者が理解できるように、そのセクションを引用としてフォーマットしました。自分の段落を引用した場合は編集してください。
カレブ

1
「コントローラーは最終的にビューにスパゲッティになってしまう」というあなたの意見に反対しなければなりません。使用しているプラ​​ットフォームやフレームワークによって異なる可能性がありますが、CocoaおよびCocoa Touchプログラミングでは、適切なコントローラーを作成するよりも、それらを省略するほうがはるかに一般的です。Objective-Cプログラマーがカテゴリーの1つを省略した場合、影響を受けるモデルになることはほぼ確実です。
カレブ

これがMVCの「適切な」解釈であることに同意する場合、MVCはまったく何も購入しません。新しいビューを作成するたびに新しいコントローラーも作成する必要があるため、MVだけでCを省くこともできます。それで、懸念の分離の理論的理由以外でそれらを分離するために苦労することのポイントは何ですか。
ダンク
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.