MVCアーキテクチャでは、モデルとビューはコントローラーにどの程度密接に結合されていますか?


16

MVCを使用するアプリがありますが、コントローラーの設計方法について少し苦労しています。たとえば、ビューはモデルのデータの一部のみを一度に表示しています。しかし、私はこれがどのように配置されるべきか正確にはわかりません。たとえば、ビューまたはモデルがコントローラーの関数を直接呼び出すのは正常ですか?ある種のインターフェースを通して?または、それらは完全にカプセル化されており、コントローラーまたは互いについて決して知りませんか?

編集と同じように。これはWebフレームワークで書かれていないカスタムアプリなので、ここではフレームワーク固有の詳細を探しているわけではなく、自分で選択する自由があります。


1
私の経験はMVCアーキテクチャに制限されているので、私は答えませんが、M&VはCではなく互いに密接に結合されています。Mは通常、CおよびV M.のいくつかのサブセットに、多くの場合のみdatabinds
スティーブン・エヴァース

8
@SnOrfus:M&VはCに結合されていますが、相互には結合されていません。
DeadMG

1
どうしてそんなに多くの答えがそんなに間違っているのでしょうか。MSのバージョンmsdn.microsoft.com/en-us/library/ff649643.aspxをお
-Reactgular

この記事を読んでください:objectmentor.com/resources/articles/taskmast.pdf
Edward Strange

回答:


15

コントローラーは、アクティビティのフローを制御します。ユーザーがこのアクションを実行すると、コントローラーはビューデータをドメインに渡し、ドメインは必要な処理を実行します。その後、コントローラーは応答に基づいて、次に表示するビューをフレームワークに伝えますそう)。

したがって、コントローラーはある程度ドメインモデルに結合する必要があります。すなわち。サービスレイヤーを間に配置することもできますが、厳密な定義により、それはドメインの一部になります。

ビューデータにも結合されますが、ビュー自体には結合されません。すなわち。「この顧客詳細を使用して顧客ビューを表示する」というだけです。次に、フレームワークは、そのビューを検索する場所を決定します。

これで、同じデータのビューモデルを使用して、ビューからドメインモデルを分離できるようになります。一部の開発者はこれを実行しますが、一部の開発者は実行しません。そして、それは主に個人的な好みの問題だと思います。

Railsでは、ドメインオブジェクト(ActiveRecord)をビューにプッシュし、ビューがそのアクセスを利用しないことを信頼することを強くお勧めします(たとえば、ビューからcustomer.saveを呼び出してはいけません)利用可能になります)。

.NETの世界では、発生してはならないことを許可しないことでリスクを軽減する傾向があり、おそらくそのために、デタッチされたビューモデルの方が人気があるように思われます。


1
ビューモデルは、単体テストに関して非常に一般的な方法です。通常、ドメインモデルまたはDTOオブジェクトをビューモデルに自動マップします。次に、ビューでビューモデルを使用します。ビューモデルは簡単にテストでき、下のレイヤーに関連付けられていません。
CodeART

7

注:ロバート・C・マーティン(別名ボブおじさん)は、彼の基調講演「失われた年の建築」でこれをより良くユーモラスな方法で説明しています。少し長いですが、たくさんの良い概念を教えています。

tl; dr:MVCの観点からアプリを考えたり計画したりしないでください。MVCフレームワークは単なる実装の詳細です。

MVCで最も紛らわしいのは、開発者がすべてのコンポーネントを接着して使用しようとすることです。

フレームワークの観点からではなく、プログラムの観点から考えてみてください。

あなたのプログラムには目的があります。データを受け取り、データを処理し、データを返します。

そうすれば、これcontrollerがプログラムの配信メカニズムです。

  1. ユーザーがプログラムにリクエストを送信します(たとえば、ショッピングカートに製品を追加します)。
  2. コントローラーはその要求(製品情報とユーザー情報)を受け取り、この要求を処理するプログラムの必要な部分を呼び出します $user->addToCart($product)
  3. あなたのプログラム(この場合addToCartuserオブジェクトの関数)は、意図した動作を行い、応答を返します(言いましょうsuccess
  4. コントローラーは、関連するものを使用して応答を準備しviewます。コントローラーオブジェクト内$this->render($cartView('success')

このようにして、コントローラーはプログラムから切り離され、配信メカニズムとして使用されます。彼らはあなたのプログラムがどのように動作するのかを知らず、リクエストのためにプログラムのどの部分を呼び出す必要があるかを知っています。

別のフレームワークを使用する場合は、アプリを変更する必要はありません。関連するコントローラーを作成して、リクエストのためにプログラムを呼び出すだけです。

または、デスクトップバージョンを作成する場合、アプリは同じままで、配信メカニズムを準備するだけです。

そしてModel。永続化メカニズムと考えてください。

オブジェクト指向の方法では、データを保持するオブジェクトがプログラムにあります。

class User {
    //...
    private $id;
    private $shoppingCart;
    //...
}

class Product {
    //...
    private $id;
    //...
}

あなたがショッピングカートに製品を追加すると、追加することができますproduct::iduser::shoppingCart

また、データを永続化する場合、modelフレームワークの一部(通常はORMを使用)を使用して、クラスをデータベーステーブルにマップできます。

使用するORMを変更する場合、プログラムは変更されず、マッピング情報のみが変更されます。または、データベースをまとめて回避したい場合は、データをプレーンテキストファイルに書き込むだけで、アプリはそのままです。


したがって、最初にプログラムを作成してください。「OO」の方法でプログラミングする場合は、言語の単純な古いオブジェクトを使用してください。最初はMVCの観点から考えないでください。


素晴らしいビデオ。ありがとう。ただし、あなたの解釈には同意しません。MVCは、ボブおじさんが持っている意味の詳細ではありません。MVCは、彼が確立している「Interactor / Entity / Boundary」パターンによく似たアーキテクチャパターンであることに注意してください。一方、Springなどの特定のMVCシステムは、実際に延期することをお勧めしています。しかし、彼が説明するように、これらのフレームワークは「MVC」と呼ばれ、この用語のやつです。
エドワードストレンジ

ええ、私は人々が何であるかを考える方法でそれを書いたMVC。それが私が書いMVC Frameworkた理由です。
ハカンデリアル

2

Martin Fowlerは、MVCパラダイムをうまく説明しています。ここに彼の記事へのリンクがありますhttp://martinfowler.com/eaaDev/uiArchs.html

分離されたプレゼンテーションに関する彼の引用に注目してください。「分離されたプレゼンテーションの背後にある考え方は、現実世界の知覚をモデル化するドメインオブジェクトと、画面に表示されるGUI要素であるプレゼンテーションオブジェクトを明確に分けることです」


1

以下は、典型的なJava SwingアプリケーションでMVCを使用する方法の簡単な例です...

ButtonとTextFieldを含むPanelがあるとします。ボタンが押されると、イベントが発生し、アプリケーションの状態が変化します。状態の変更が登録されると、TextFieldは無効になります。

これは、単純なMVCアプリケーションで採用される典型的なアプローチです...

コントローラーは、それ自体をビューのイベントのリスナーとして登録します。ボタンがクリックされると、ビュー自体はイベントを処理しません。コントローラーが行います。コントローラは、Swing関連のイベントを処理する必要があるため、Swing固有です。

コントローラーはこの通知を受け取り、誰がそれを処理する必要があるかを決定する必要があります(ビューまたはモデル)。このイベントはアプリケーションの状態を変更するため、データとプログラムロジックを担当するモデルに情報を転送することにします。コントローラにプログラムロジックを配置するミスをする人もいますが、OOPでは、モデルはデータと動作の両方を表します。これについてのMartin Fowlerの記事を読んでください。

メッセージは、適切なコンテキストでモデルによって受信されます。つまり、Swingへの参照やその他のGUI固有の参照はまったくありません。このメッセージは、モデルおよびモデルのみに伝えます。モデルにjavax.swingステートメントをインポートしていることに気付いた場合、モデルを正しくコーディングしていません。

その後、モデルはその状態を「無効」に設定し、このモデルの変更を関係者に通知します。このイベントに関心を持つビューは、モデル変更のオブザーバーとしてすでに登録されています。モデルの状態変更イベントがビューによって取得されると、TextFieldを無効にします。また、ViewがControllerを経由せずにモデルから直接読み取り専用情報を取得することも合法です(通常、そのようなアクティビティのためにModelによって公開される特定のインターフェイスを介して)

プレゼンテーションとビジネスロジックとデータレイヤーとの間のこのような疎結合を促進することにより、コードのメンテナンス性が大幅に向上します。システムが成長するにつれて、MVCへのアプローチも大きくなります。たとえば、階層MVCは、サブシステムを結合せずにMVCトライアドをリンクして大規模なエンタープライズ規模のシステムを形成するためによく使用される拡張機能です。


0

カップリング(回避したいソート)には、2つのクラス間の相互依存関係が含まれます。つまり、Fooはバーに依存し、BarはFooに依存するため、一方を変更せずに他方を実際に変更することはできません。それは悪いことです。

ただし、いくつかの依存関係を避けることはできません。クラスはお互いについて少し知っている必要があります。

MVCパターンでは、コントローラーはドメインモデルとプレゼンテーションビュー間の通信を制御します。そのため、コントローラーはモデルについて十分な知識がなくてはならないため、モデルが行うべきことを要求する必要があります。また、コントローラーはクライアントまたはユーザーに表示できるようにビューについて十分に知っている必要があります。そのため、モデルコントローラーは両方に依存しています。ただし、ビューはコントローラーがなくても完全に存在できます。依存関係はありません。同様に、モデルにはコントローラーに依存性がありません-それは単にそれが何であるかです。最後に、モデルとビューは互いに完全に分離されています。

基本的に、コントローラーは、ビューをモデルから切り離す間接レベルであるため、互いを知る必要はありません。


ああ、だからこそ、下票は間違っている。コントローラーが両方に依存しているということです。ど!
マシューフリン

-5

私の経験では、一般的にモデルにのみ依存することが多いオブザーバーとして、ビューではなく、特定の1 ...それはすべてのそのような結合を持っている場合。

ビューは通常、見ているものに結合します。表示されているものから切り離すことができるビューを思い付くのは難しいですが、場合によっては、部分的なカップリングまたは何かを持つことができます。

コントローラーはしばしば両方に結合する傾向があります。また、ビューイベントをモデルの変更に変換するのが仕事なので、これもある程度理にかなっています。

もちろん、これは私が観察した傾向に過ぎず、特定の例については何も実際に言っていません。

MVCが何であり、カップリング関係がどのような傾向があるかを理解するには、MVCがどのようになったかを調べる必要があります。MVCが作成された環境は、ダイアログを構築できるフォーム要素としての「ウィジェット」が存在しない環境でした。「ビュー」はボックスであり、それはものを描きました。テキストビューは、テキストを描画するボックスになります。リストビューは、リストを描画するボックスでした。「コントローラー」は、そのビューで発生したUIシステムからすべてのマウスおよびキーボードイベントを受け取りました。「textChanged」または「selectionChanged」イベントはありませんでした。コントローラーは、これらすべての低レベルイベントを取得し、モデルとの相互作用を生成します。モデルは、変更されるとビューに通知します。それ以来、この関係を「オブザーバー」と見なすようになりました。

これがMVCパターンの本質です。この種の低レベルUIプログラミングは一般的に行われなくなったため、MVCはさまざまな方向に進化しました。今日その名前で使われているものは、MVCのようなものではなく、実際には別のものと呼ばれるべきものです。全体としてより大きなオブジェクトと対話するダイアログの意味で使用することもできます。しかし、多くのより良い選択肢があります。

基本的に、MVCが解決することを意図していたものはすべてウィジェットの内部で発生するため、使用する必要はありません。


よく知っていると思う人のために:

http://www.codeproject.com/Articles/42830/Model-View-Controller-Model-View-Presenter-and-Mod

http://msdn.microsoft.com/en-us/library/ff649643.aspx

他にもあるはずですが、それらはGoogleのリストのトップにすぎません。ご覧のとおり、このモデルは多くの実装のビューインターフェイスに大きく依存しています。通常、モデルは観察可能であり、ビューは観察者です。

しかし、なぜ事実が邪魔するのか...

別の回答ですでに投稿された記事も私の声明をサポートしています:

http://martinfowler.com/eaaDev/uiArchs.html

設計業界の誰もが間違っていると人々が言い続けたいと思うなら、それは大丈夫です。


4
これは明らかに間違っています。モデルはビューに依存してはいけません!そのビューが抽象的またはインターフェースであっても。モデルはプレゼンテーションから完全に切り離されるべきです!
ファルコン

3
答えが間違っています。モデルはビューやコントローラーに依存しません。
CodeART

2
@Crazy Eddie「私の経験では、一般にモデルは特定のビューではなく、多くの場合オブザーバーとしてのビューにのみ依存します」と引用されています。「しかし、モデルはビューにもコントローラーにも依存しません。」引用された記事も読んだことがありますか?それのように見えません。
CodeART

2
@Crazy Eddie:くだらないコードプロジェクトの誰かが何を書いているかは気にしません。これは恐ろしいデザインです。オブザーバーを使用して変更をリッスンすることは問題ありませんが、ドメインモデルにプレゼンテーションインターフェイスを配置することは非常に間違っています。記事から引用されたコードには、MVCに関していくつかの基本的な方法で欠陥があります。モデルを暗黙的にコントローラーに依存させることもできます。なんてくだらない。
ファルコン

3
@クレイジーエディ:笑@ downvote大暴れ。私はあなたを励ましましたか?
ファルコン

-7
  • コントローラーはモデルをビューにディスパッチし、ビューから送信されたモデルを処理しますが、ビューまたはモデルに密結合されていません。

コントローラーがビューに密結合されていれば、Webフォームの世界になります。テンプレートファイルに関連付けられるコードビハインドが必要です(ASP.NET Webフォームに適用可能)

このため、コントローラーはモデルまたはビューに結合されていません。これは、リクエストを処理し、レスポンスを送信するための単なるメカニズムです。

  • ビューはモデルに密接に結合されています。モデルを変更(たとえば、プロパティを変更)すると、ビューを変更する必要があります。

  • モデルはビューに密結合されていません。ビューに変更を加えても、モデルには影響しません。

  • モデルは、それが使用される可能性のあるコントローラーまたはビューについて何も知りません。したがって、モデルはビューまたはコントローラーに密結合されていません。

これについて考える別の方法:

  • コントローラーに変更を加えます-ビューとモデルは影響を受けません

  • モデルに変更を加えます-モデルに依存しているため、ビューが壊れます

  • ビューを変更します-モデルとコントローラーは影響を受けません

MVCプロジェクトのこの疎結合は、ユニットテストを容易にするものです。


1
これは非常に間違っているので面白くない。説明する価値さえありません。この答えを完全に無視してください。
-Reactgular

1
@MathewFoscarini泣き止んで「正解」を残す
CodeART

2
笑、MVCの背後にある全体の設計理論は、それらが互いに依存していないということです。
-Reactgular

より多くの情報を残しましたが、それが理にかなっていることを願っています
-CodeART
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.