Model-View-Controllerパターンでのモデルとビューの役割は理解していますが、コントローラーが必要な理由を理解するのに苦労しています。
MVCアプローチを使用してチェスプログラムを作成していると仮定しましょう。ゲームの状態がモデルになり、GUIがビューになります。この場合、コントローラーは正確に何ですか?
これは、たとえばタイルをクリックしたときに呼び出されるすべての関数を備えた単なる別のクラスですか?ビュー自体でモデルのすべてのロジックを実行しないのはなぜですか?
Model-View-Controllerパターンでのモデルとビューの役割は理解していますが、コントローラーが必要な理由を理解するのに苦労しています。
MVCアプローチを使用してチェスプログラムを作成していると仮定しましょう。ゲームの状態がモデルになり、GUIがビューになります。この場合、コントローラーは正確に何ですか?
これは、たとえばタイルをクリックしたときに呼び出されるすべての関数を備えた単なる別のクラスですか?ビュー自体でモデルのすべてのロジックを実行しないのはなぜですか?
回答:
あなたの例を使用すると、コントローラーが合法的な動きであるかどうかを決定します。コントローラーは、モデルから受け取った情報を使用して、起動時にボード上のピースを配置する方法をビューに知らせます。コントローラーで処理できるものは他にもありますが、重要なのはそのレイヤーのビジネスロジックについて考えることです。
コントローラーが行うことは、サインアップページのように情報をやり取りすることだけです。また、コントローラーを開発の難しい部分とする場合もあります。たとえば、ルールを適用したり、複雑な数学を実行したりするなど、そのレイヤーで行う必要のあることがたくさんあるためです。コントローラーを忘れないでください!
ビュー自体でモデルのすべてのロジックを実行しないのはなぜですか?
コントローラーは、モデルとビューを結合する接着剤であり、モデルとビューを分離する断熱材でもあります。モデルはビューについて何も知らないはずであり、逆もまた同様です(少なくともAppleのMVCバージョンでは)。コントローラーは双方向アダプターのように機能し、ビューからのユーザーアクションをモデルへのメッセージに変換し、モデルのデータを使用してビューを構成します。
コントローラーを使用してモデルとビューを分離すると、コードの再利用性、テスト性、柔軟性が向上します。チェスの例を考えてみましょう。モデルにはもちろんゲームの状態が含まれますが、動きが合法であるかどうかを判断したり、ゲームが終了したときに決定したりするなど、ゲームの状態の変更に影響するロジックも含まれます。ビューにはチェス盤と駒が表示され、駒が動くとメッセージが送信されますが、駒の背後にある意味、各駒がどのように動くかなどについては何も知りません。コントローラーはモデルとビューの両方を知っていますプログラムの全体的な流れ。ユーザーが「新しいゲーム」ボタンを押すと、ゲームを作成するようモデルに指示し、新しいゲームの状態を使用してボードをセットアップするコントローラーです。ユーザーが移動した場合、
モデルとビューを別々にしておくことで得られるものを見てください:
他のモデルまたはビューを変更せずに変更できます。いずれかを変更するときにコントローラーの更新が必要になる場合がありますが、これはある意味で利点の一部です。変更される可能性が最も高いプログラムの部分はコントローラーに集中しています。
モデルとビューの両方を再利用できます。たとえば、有名なゲームを説明するためのモデルとしてRSSフィードと同じチェスボードビューを使用できます。または、同じモデルを使用して、ビューをWebベースのインターフェイスに置き換えることもできます。
モデルとビューの両方のテストを簡単に作成して、それらが期待どおりに機能することを確認します。
多くの場合、モデルとビューの両方が標準パーツを利用できます。配列、マップ、セット、文字列、およびモデルの他のデータコンテナー。ビューのボタン、コントロール、テキストフィールド、画像ビュー、テーブルなど。
この一般的な設計パターンを実装する方法は多数ありますが、基本的な考え方は、必要に応じてさまざまな懸念を分離することです。MVCは、次の意味で優れた抽象化です。
Model:そのデータを表し、それが意味するものは何でも
View:ユーザーインターフェイスを表し、それが意味するものは何でも
Controller:そのモデルとビューを相互作用させる接着剤を表します。
全体を指定しないため、非常に柔軟です。多くの人々は、各要素が何を意味するのか、これらの代わりにどの名前を使用するべきか、実際に3つまたは2つまたは4つまたは5つのコンポーネントが存在するかどうかの詳細を議論する多くの帯域幅を無駄にしていますが、それはポイントを失っていますある程度。
アイデアは、ロジックの異なる「チャンク」を分離して、重複しないようにすることです。プレゼンテーションをまとめ、データをまとめ、ロジックをまとめ、コミュニケーションをまとめます。などなど。ある程度、これらの関心領域が重ならないほど、それらで興味深いことをするのが簡単になります。
本当に心配する必要があるのはこれだけです。
これまでのところ、すべての良い答え。私の2セントは、コントローラーを何とどこのような質問で主に構築されていると考えるのが好きだということです。
これらの小さなスニペットは、MVCが伝えようとしている抽象化と概念を私がどのように思い出そうとしているかの例です。私の3つの主な思考プロセスは、何、どこ、どのようにですか。
内容と場所=>コントローラ方法と時期=>モデルとビュー
本質的に、私のコントローラーのアクションは小さくてコンパクトである傾向があり、それらを読むとき、時間の無駄のように見える傾向があります。綿密な調査では、彼らは信号機として機能し、さまざまな要求を適切な労働者に送りますが、実際の作業は一切行いません。
イベントハンドラーを処理するときに実際に機能しますが、ビューとモデル間の相互作用を処理するコントローラーが必要です。ビューがモデルについて何も知らないようにすることが理想的です。それについて考えてください。jspですべてのデータベース呼び出しを直接行いたいですか?(ログインルックアップのような場合を除きます。)ビューがデータをレンダリングし、ビューレンダリングロジックではなく、ビジネスロジック自体を持たない限り、ビジネスロジックを持たないようにします。
GWTでは、MVPでよりクリーンな分離を実現します。ビューにビジネスロジックはまったくありません(正しく行われている場合)。プレゼンターはコントローラーとして機能し、ビューにはモデルに関する知識がありません。モデルデータは、単にビューに渡されます。
ドキュメントビュー(モデルビュー)は、MFCで記述された大半のWindowsアプリの標準モデルであるため、多くの場合に機能する必要があります。
Model-View-Controllerパターンでのモデルとビューの役割は理解していますが、コントローラーが必要な理由を理解するのに苦労しています。
(少なくとも最初に説明したように)モデルのポイントはドメインモデルになることです。ビューは、ドメインモデルをユーザーに表示することになっています。コントローラーは、低レベルの入力を高レベルのモデルの話にマッピングすることになっています。私の知る限り、理由は次のようなものです:A)SRPの高レベルの使用。B)モデルはアプリの重要な部分であると考えられていたため、重要ではなく、より速く変化するものを排除します。C)簡単にテスト可能な(およびスクリプト化可能な)ビジネスロジック。
盲人がチェスプログラムを使用できるようにしたい場合は、ビューを可聴バージョンとキーボードで動作するコントローラーに交換します。メールでゲームを追加する場合、テキストを受け入れるコントローラーを追加します。ゲームのネットバージョン?ソケットからコマンドを受け取るコントローラーがジョブを実行します。素敵な3Dレンダリングを追加します。クールな新しいビューです。ゼロモデル変更に必要なチェスはまだチェスです。
入力とモデル表現を混ぜると、その機能を失います。突然、チェスはチェスではなく、キーボードまたはネットワーク接続のチェスとは異なるマウスのチェスです。
MVCは馬鹿げていると思う。特定の分野ではうまく機能しているかもしれないが、個人的に私が書いたウェブサイトでさえmvcには向いていない。フロントエンド、バックエンドを聞いて、データベースエンドまたは他のエンドエンドではない理由があります
IMOにはAPI(バックエンド)とAPIを使用するアプリ(フロントエンド)が必要です。GETリクエストをコントローラー(単にバックエンドAPIを呼び出す)とhtmlを呼び出してビューを呼び出すことができますが、通常、ビューが純粋なhtmlまたはモデルとしてバックエンドAPIであるという話を聞くことはありません。
IMOすべてが堅牢なAPIである必要があります。実際、それらは(クリーンでよく構築されているように)堅固である必要はありませんが、その内部はプライベートのままである必要があり、APIのアプリ/フロントエンド/外部は決してデータベース接続を要求したり、生のクエリを実行したりすることはありません
コード/デザインに接着剤が含まれている場合、これで問題ありません。チェスゲームでGUIのスキンを編集できるマークアップがある場合、GUIは座標/入力を収集し、MovePiece(srcPosition、dstPostion)を呼び出します(有効な移動であるかどうかを示すブールまたは列挙型を返すことがあります) )そして、すべてのロジックがモデル内にあることを確認したら、必ずMVCと呼びます。しかし、私はまだクラスとAPIによって物事を整理し、すべてに触れるキッチンシンククラスがないことを確認します(すべてのことを知る必要があるAPIもありません)。
静的なWebページを表示するブラウザーを考えてください。モデルはHTMLです。ビューは、画面上の実際の結果です。
JavaScriptを追加します。それがコントローラーです。ユーザーがボタンをクリックするか、イベントがJavaScriptに送信されるものをドラッグすると、何をするかを決定し、基になるHTML(モデル)を変更し、ブラウザー/レンダラーはそれらの変更を画面(表示)に表示します。
おそらく、別のボタンがクリックされ、イベントが何らかのハンドラー(コントローラー)に送信され、さらにデータをWebサービスに送信する要求が発生する可能性があります。次に、結果がHTML(モデル)に追加されます。
コントローラーはイベントに応答し、モデル内にあるもの、したがって画面/ビューにあるものを制御します。
少し前に戻ると、ブラウザー全体をビュー、サーバーをコントローラー、データをモデルと考えることができます。ユーザーがブラウザー(サーバー)に送信したイベント(コントローラー)のボタンをクリックすると、リソースがHTMLページ(モデル)として収集され、ブラウザーに戻されて表示されます(表示)
asp、php、javaのいずれのサーバーでも、「コード」(コントローラー)はクリックイベントを受信し、データベースまたはドキュメントリポジトリ(モデル)を照会し、HTMLを作成します。サーバーの観点から見ると、そのすべてのアクションの結果は、基礎となるデータストア(モデル)のビュー(HTML)です。しかし、クライアントの観点から見ると、サーバーへのリクエストの結果はそのモデル(HTML)です。
HTMLでJavaScriptをごちゃごちゃにしたり、モデル、ビュー、HTMLでPHPをごちゃごちゃにしたりしても、コントローラーは存在します。サーバーへのリクエストとサーバーからの応答を単純な双方向道路と考えても、モデル、ビュー、コントローラーがあります。
私の経験では、従来のデスクトップ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デザインパターンによって与えられます。