web-dev-qa-db-ja.com

MVCは反OOPではありませんか?

OOP=の背後にある主なアイデアは、データと動作を単一のエンティティ(オブジェクト)に統合することです。手続き型プログラミングには、データと、データを変更する個別のアルゴリズムがあります。

Model-View-Controllerパターンでは、データとロジック/アルゴリズムはそれぞれ別個のエンティティ、モデルとコントローラーに配置されます。同等のOOPアプローチでは、モデルとコントローラーを同じ論理エンティティに配置するべきではありませんか?

62
m3th0dman

MVCは、UIアーキテクチャである 懸念の分離 の演習です。これは、プレゼンテーションがコンテンツから分離されていないが原因でユーザーインターフェイスで発生する可能性のある複雑さをまとめる方法です。

理論的には、すべてのオブジェクトは、それらに含まれるデータを操作する動作を持つことができ、そのデータと動作は カプセル化 のままです。実際には、特定のOOPオブジェクトには、そのデータに対応するロジックがある場合とない場合がある、またはまったくロジックがない場合があります(a Data Transfer Object 例)。

MVCでは、ビジネスロジックはコントローラーではなくモデルに組み込まれます。コントローラは、実際にはビューとモデルを結び付ける単なる仲介役です。したがって、モデルでは、データと動作を同じ場所に置くことができます。

しかし、そのような配置であっても、厳密なデータ/動作の融合を保証するものではありません。データのみを含むオブジェクトは、ロジックのみを含む他のクラスで操作できます。これは、OOPの完全に許容できる使用法です。


具体的な例を挙げましょう。これは少し工夫されていますが、Currencyオブジェクトがあり、そのオブジェクトは、ドルに固定された使用可能な通貨でそれ自体を表す機能を持っているとしましょう。したがって、次のようなメソッドがあります。

public decimal Yen { get { return // dollars to yen; } }
public decimal Sterling { get { return // dollars to sterling; } }
public decimal Euro { get { return // dollars to euro; } }

...そしてその動作はCurrencyオブジェクトでカプセル化されます。

しかし、ある口座から別の口座に通貨を送金したい場合、またはいくつかの通貨を預金したい場合はどうなりますか?その動作もCurrencyオブジェクトにカプセル化されますか?いいえ、そうではありません。ウォレットのお金は、ウォレットから銀行口座に送金できません。あなたはそのお金をあなたの口座に入れるのを助けるために1人以上のエージェント(窓口またはATM)を必要とします。

したがって、その動作はTellerオブジェクトにカプセル化され、CurrencyおよびAccountオブジェクトを入力として受け入れますが、ビット自体を除いて、データ自体は含まれません。ローカル状態(またはTransactionオブジェクト)を使用して、入力オブジェクトの処理を支援します。

45
Robert Harvey

MVCはmuch単一オブジェクトよりも高い抽象化レベルで機能し、実際、3つ(モデル、ビュー、コントローラー)のそれぞれは通常、それぞれがデータと動作の両方を持つ多くのオブジェクトで構成されます。

データと振る舞いをカプセル化するオブジェクトが、一般にプログラムの優れた基本的なビルディングブロックであることは、それが抽象化のすべてのレベルで、すべての目的のための最良のパターンであることを意味しません。

74

OOPは、それぞれ独自のデータと独自の動作を持つオブジェクト間の相互作用を制限しません。

アリとアリのコロニーの類比を考えてみてください。個々のアリの行動(1日中走り回って、食べ物を持ち込む)は、コロニー全体の行動とは異なります(最も望ましい場所を見つけて、アリを増やします)。 MVCパターンは、アリのコロニーの望ましい社会構造を表しますが、OOP=は、個々のアリの設計を導きます。

71
dasblinkenlight

OOPは 懸念の分離 についても重要です。つまり、異なるオブジェクトの異なる役割/責任を分離することです。

MVCは次のコンポーネントに分かれています。

  • モデル:データとそのビジネスロジック
  • 表示:データの表現
  • Controller:モデルとビューの間の調整。

したがって、これらの責任は明確に異なり、実際には複数のエンティティに分離する必要があります。

19
marco-fiset

Model-View-Controllerパターンでは、データとロジック/アルゴリズムはそれぞれ別個のエンティティ、モデルとコントローラーに配置されます。

モデルとコントローラーは、2つの異なる役割です。モデルには状態とロジックの両方があり、コントローラーには状態とロジックの両方があります。それらが通信するという事実はどちらか一方のカプセル化を壊しません-コントローラはモデルがそのデータを保存するか方法を知らないか気にしません、またはコントローラーがデータの一部を取得または更新したときのデータへの影響モデルは、コントローラーがモデルが提供するデータをどのように処理するかを知りません。

このように考えてください。オブジェクトがカプセル化を解除せずにデータをやり取りできなかった場合、実際には1つのオブジェクトしか持てません。

同等のOOPアプローチでは、モデルとコントローラーを同じ論理エンティティに配置するべきではありませんか?

MVCisan OOPアプローチ-具体的には、オブジェクトを使用してプログラムを効果的に編成する方法を決定するためのレシピです。そしてnoの場合、モデルとコントローラーは同じエンティティであってはなりません。コントローラーを使用すると、モデルとビューを分離できます。モデルとビューを互いに独立させておくと、テストと再利用の両方が容易になります。

18
Caleb

MVCは、オブジェクトが相互作用する賢明な方法を記述するパターンです。それ自体はメタクラスではありません。 OOは、エンティティの動作とデータ、およびエンティティがどのように相互作用するかを説明することであり、システム全体を1つの巨大なオブジェクトに統合することではありません。

コントローラはモデルの動作を表しません。コントローラは、アプリケーション全体の動作を完全に表します。つまり、ユーザーが実行できることとユーザーが表示できることを表します。

コントローラとモデルを1つとして表示するのは誤りです。それらは異なる目的、異なるセマンティクスを持っているため、1つのオブジェクトに統合すべきではありません。

2
superM

モデルレイヤーは、コントローラーレイヤーが単なるロジックである以上、単なるデータではありません。

コントローラレイヤには、その目的のためのオブジェクトの完全なコレクションがあります。ビューから入力を受け取り、その入力をモデルが処理できるフォームに変換するためのオブジェクトがあります。 Struts Javaフレームワークは、そのアクション/フォームモデルの良い例です。フォームにはユーザーからの入力が入力され、アクションに渡されます。アクションはそのデータを取得して使用しますモデルを操作します。

同様に、モデルレイヤーはすべてデータで構成されているわけではありません。たとえば、ユーザーオブジェクトを例にとります。データベースからユーザーを取得するコード、またはユーザーを注文に関連付けるためのコード、またはユーザーのアドレスが会社のサービスの範囲内にあることを検証するためのコードが必要な場合があります...画像。これはコントローラーロジックではありません。これはビジネスロジックであり、モデルレイヤーをビジネスロジック用のサービスレイヤーまたはマネージャーレイヤー、データベースアクセス用のDAO(データベースアクセスオブジェクト)レイヤーなどのいくつかのレイヤーに分割することが多くなっています。

MVCは、個々のモデル操作を整理する方法ではありません。それはそれよりも高いレベルで機能します。これは、アプリケーションへのアクセス方法を整理する方法です。ビューは、データとそれを操作するための人間のアクションを提示するためのものであり、コントローラーは、ユーザーアクションとさまざまなビューとの間の変換のためのものです。モデルは、ビジネスデータとそれが存在するビジネス上の理由が存在する場所です。

2
Michael K

OOPのポイントは、データと機能をグループ化することです一緒に属している。一部のデータに基づく計算では、alwaysはそのデータに属します。

MVCでは、データ(ビュー)を表示する機能は、データ(モデル)とは別に保持されます。何故ですか?具体的には、基になるデータを変更せずに表示ロジックを変更できるようにするためです。同じデータを別の方法で表示する必要があるときや、ディスプレイハードウェアの特性が変わったとき、またはWindowsからLinuxに切り替えたときに、ビューを簡単に変更できます。または、2人が同じデータを2つの異なる方法で見ることを望む場合。

MVCは、OOP=と競合していません。実際には、オブジェクト指向の原則の正しいアプリケーションから派生しています。

2
DJClayworth

私が理解しているように;議論はコンポーネントベースのアーキテクチャ対OOPです。そして、宗教戦争に入るまでもなく、両者は同じことを説明していると思います。それを別の角度から見るだけです。

たとえば、OOP/OODの全体のポイントは、コードをよりモジュール化して再利用可能にすることです。はい?

これは、まさにコンポーネントベースのアーキテクチャの目標です。ですから、彼らは何よりも似ています。

MVCは、OOPの自然な進化形にすぎないと思います。あえて言っておきますが、オブジェクトを整理するためのより良い方法、懸念事項の分離、コードの再利用です。

0
djm

モデルオブジェクトにバインドされた永続データを、モデルが相互作用するデータベースのアプリケーションデータと混同していると思います。モデルには、データベースの操作とトランザクションの実行に関するビジネスロジックとルールが含まれています。今日のセールがあるかどうか、ユーザーがVIPステータスの資格を持っているかどうかなどの内部状態フラグを設定およびチェックし、データへのアクセス、設定、または操作するときにロジックを分岐します。これは、一連のメソッドと永続的な値またはデータのカプセル化に関してオブジェクトについて説明するときに話しているフラグです。

モデルオブジェクトが、どのビジネスルールが機能しているかを確立するためのデータを維持するように、コントローラーはIMOが、ユーザーがログインしているか、有効なクレジットを持っているかなど、アプリの動作に関連するより一般的なアプリケーション状態データを保持する必要がありますカードデータが所定の位置にあります。モデルメソッドはそもそもこれらの状態を決定しますが、コントローラーがビジネスの実行方法やデータトランザクションの実行方法に適用されない場合、コントローラーが一般的なアプリフローに関連するフラグを維持することは理にかなっています。ログインしていないと判断したら、別のログイン試行が行われていることが明らかになるまで、モデルをユーザー状態チェックに悩まさないでください。

同様に、適切なビューオブジェクトと、ほとんどのサーバー側Webフレームワークで見られるより一般的なHTMLテンプレートを使用します。ユーザーのカラー設定が読み込まれると、そのデータを保持して実行するビューになります。設定の読み込み、検証、変更はすべてモデルの問題ですが、変更が発生するまで一度だけモデルの問題である必要があります。

IMO、コントローラーがビューとモデルを内部集約オブジェクトとして持つ複合オブジェクトであってはならないということは何もありません。これは、UIウィジェットファクトリーのような小規模にMVCを適用する場合に実際に意味があります。コントローラーは、ビューとモデルがどのように相互作用するかのデータとロジックの詳細を埋め込みながら、より高いレベルのアプリオブジェクトにインターフェイスを公開するための理想的な場所だからです。ただし、コントローラーが実際に最上位レベルのオブジェクトであるモノロシックアプリオブジェクトの場合は、あまり意味がありません。

0
Erik Reppen