MVCアンチOOPではありませんか?


62

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

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


11
なぜ彼らは同じ論理エンティティにいる必要があるのでしょうか?なぜそれが有利なのか、なぜOOPがこの取り決めを決定するのかについては述べていません。
ロバートハーベイ

26
さて、ビジネスロジックはコントローラーではなくモデルに組み込まれます。コントローラーは、実際にはビューとモデルを接着するための単なる仲介役です。そのため、モデルでは、同じ場所にデータと動作があります。
ロバートハーベイ

2
何?データと動作を統合することは、まさにOOPのすべてです。
アンディ

3
OOPは、実装をインターフェイスから分離することです。インターフェースは振る舞いに関係があり、実装はデータに関係があります(データが隠される傾向がある理由です)。したがって、OOPはデータと動作を統合することではなく、それらを分離することです。
カズ

5
とにかく、すべてのデータと動作を1つのクラスに詰め込みたくありません。OOPプログラムは、複数のクラスを使用してオブジェクトのフレームワークを作成します。とにかく、何かが「反OOP」であれば、それは良いことかもしれません。OOPは、万能ではありません。OOPは実にひどいです。OOPを乗り越えるときです。
カズ

回答:


45

MVCは、UIアーキテクチャであるSeparation of Concernsの演習です。それはプレゼンテーションがコンテンツから切り離されないためにユーザーインターフェースで起こることができる複雑さを囲い込む方法です。

理論的には、すべてのオブジェクトに含まれるデータを操作する動作があり、そのデータと動作はカプセル化されたままになります。実際には、特定のOOPオブジェクトには、そのデータに対応するロジックがある場合とない場合があります。または、ロジックがまったくない場合もあります(たとえば、データ転送オブジェクト)。

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ますが、入力オブジェクトの処理を支援するためのローカル状態の一部(またはオブジェクト)を除き、データ自体は含まれません。


また、どのエンティティ/パッケージTellerに配置する必要がありますか?ではControllerどこからTeller'sメソッドが呼び出されたりしているModel、それはビジネスロジックの一部だから?
m3th0dman

Tellerに入りますがModel、コントローラから呼び出すことができます。これはビジネスドメインの一部です。
ロバートハーベイ

モデルをビジネスルールに使用すると、MVCが半効果的なパターンになると常に考えていました。実際のアプリケーションへのアダプターにモデルを使用し、アダプターとビューの間でコントローラーを仲介させることは、SoCを達成する上で常にはるかに効果的です。
ヤムマルコビッチ

@YamMarcovic:どういう意味かわかりません。モデルは一種のキャッチオールです。実際には、ビジネスルールは通常、独自のサービスレイヤーに配置されますが、モデルの一部と見なされます(たとえば、個々のコントローラーメソッド内で特定のビジネスルールをエンコードすることはできません)。コントローラーが仲介役であることは正しいです。
ロバートハーベイ

5
ほとんどの人がMVCについて読んだだけで間違っていると思うことの1つは、「ビジネスロジック」が何を意味するかについての過度に広い仮定です。モデルをポップアウトして、同じビジネス目標を持ち、まったく異なるアプリケーションロジックを持つコントローラーを介して非常に異なるアーキテクチャを持つ新しいアプリで、最小限の修正なしでモデルを使用できない場合、それは間違っていますIMO。もちろん、あなたが持っている他のすべてのものの組み合わせからビューを切り離すことには価値がありますが、軽量の構造体としてのCは、分離の重要なポイントを逃しているように感じます。
エリックReppen

73

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

データと動作をカプセル化するオブジェクトは、一般的なプログラムの優れた基本的な構成要素であるということは、すべての抽象化レベルであらゆる目的に最適なパターンであることを意味しません。


オブジェクト指向のアプローチは、抽象化のレベルで拡張できます。たとえば、古典的な階層化アーキテクチャがOOP的なものではなく、手続き型であるために現れたドメイン駆動設計の背後にある理由を参照してください。これは、MVCよりも高い抽象化レベルで発生します。
m3th0dman

6
@ m3th0dman:広範で包括的な一般論を述べています。MVCがスパゲッティコードの悪夢であるWinformsまたはWebformsを排除する方法など、詳細を議論するのはどうですか?
ロバートハーベイ

3
@ m3th0dman:これはDDDの非常に単純化された特性です。
マイケルボルグ

1
@RobertHarvey MVCがスパゲッティを排除するので、MVCが優れている理由の反対点であることを確認するために、ここでは実際にコンテストを行っていません。私は同意しますが、MVCが手続き型パターンで実装されることもよく見ます。質問するのは適切な質問だと思います。むしろ、質問するのは「人々はどれくらいの頻度でMVCを手続き的に実装するのでしょうか?」
ジミー・ホッファ

1
@Robert Harvey質問の目的は、MVCの良し悪しについてではありません。それは、オブジェクト指向の原則に基づいているかどうかに関係しています。
m3th0dman

71

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

アリとアリのコロニーの例えを考えてみましょう。個々のアリの行動(一日中走り回って餌を持ちます)は、コロニー全体の行動とは異なります(最も望ましい場所を見つけて、アリを増やします)。MVCパターンは、アリのコロニーの望ましい社会構造を記述し、OOPは個々のアリの設計をガイドします。


5
+1:私は通常、類推による説明が嫌いですが、これは素晴らしいです。
マイケルボルグワード

@Calebこれは素晴らしい点です、ありがとうございました!
-dasblinkenlight

19

OOPは、関心の分離、つまり異なるオブジェクトの異なる役割/責任を分離することでもあります。

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

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

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


単一責任の原則がOOPを効果的に使用するのに役立つことは確かですが、「OOPは単一責任の原則でもある」と言うのは一苦労です。それは逆に思えます。
カレブ

@カレブええ、私はあなたの意味を理解しています。言い換えることができるかもしれませんが、あなたはポイントを得る。
marco-fiset

18

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

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

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

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

MVC OOPアプローチです。具体的には、オブジェクトを使用してプログラムを効果的に編成する方法を決定するためのレシピです。そしてノー、モデルとコントローラが同じエンティティであってはなりません。コントローラーにより、モデルとビューを分離できます。モデルとビューを互いに独立した状態に保つことで、テストと再利用の両方が可能になります。


コントローラーにはロジックがありますが、状態がほとんどないか、まったくないことを願っています。コントローラーにはどのような状態があると考えていますか?
マシューフリン

1
@MatthewFlynnまず、コントローラーはビューとモデルについて知る必要があります。それを超えて、それは我々が話しているMVCの特定のどのような味に依存してもよいが、一般的には、コントローラはに関連した状態を維持する可能性がどのようにモデルのお得な情報に対し、(例えば、現在の選択)の情報が表示されなければならないの情報が表示されます。
カレブ

1
@MattFenwick「フレーバー」について私が言っているのは...コントローラーに何を保存し、モデルに何を保存するかは、好みと慣習の問題です。Cocoa / Cocoa Touchでは、コントローラで現在の選択やユーザー設定などを保持するのが一般的です。一部のWebフレームワークで使用されているMVCは、モデルにほとんどすべてを配置し、コントローラーにはほとんど配置しません。YMMV。
カレブ

4
@MatthewFlynnほとんどがあなたに同意しますが、IMO、人々はビジネスロジックを想定よりも広いカテゴリーに取ります。このコントローラーは、ビジネスロジックと混同されることが多いアプリケーションロジックを処理します。理想的な懸念の分離では、ビジネスオブジェクトを変更することなく、同じビジネス目標に対応するまったく異なるアプリアーキテクチャでモデルオブジェクトを再利用できるはずです。新しいアプリケーションがしなければならないことは、インターフェースを使用して、返され処理されたデータとトランザクションを独自に処理することだけです。
エリックReppen

1
@MattFenwick:マルチユーザーアプリケーションを検討してください。モデルとコントローラーの間に線を引く明らかなポイントは、モデルが共有状態を処理し、コントローラーがローカル状態を処理することです。現在の選択はローカルであるため、コントローラーに配置されます。
ジャン・ヒューデック

4

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


2

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

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


2

モデル層は単なるデータではなく、コントローラー層は単なるロジックです。

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

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

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


2

OOPのポイントは、一緒に属するデータと機能をグループ化することです。一部のデータに基づく計算は、必ずしもそのデータに属するとは限りません。

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

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


0

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

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

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

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


0

私が理解したように。引数は、コンポーネントベースのアーキテクチャとOOPです。そして、宗教戦争に入ることなく、彼らは両方とも同じことを述べていると思います。さまざまな角度から見ているだけです。

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

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

MVCはOOPの自然な進化であり、あえて言うと思います。オブジェクトの整理、懸念の分離、コードの再利用のためのより良い方法。


私は、MVCとコンポーネントベースのアーキテクチャはOOPアプローチの領域外にない設計パターンであると思いますが、OOD / OOPは、国境を接するユビキタスプログラミングの使用方法に関する思考と学問の学校の混乱と衝突の単なる束です適切に構築します。2つのカテゴリを比較することは、正方形と、正方形の描画に使用したペンを比較するようなものです。
エリックReppen

-1

私はこのパーティーに遅れており、私の前にすべての答えを考えて、私は提供する多くの新しいものがないことを認めます。しかし、質問はパターン自体に関するものではなく、実装に関するものであるように思えます。MVC自体は、特定の方法論には役立ちません。実際、MVCパターンでプロシージャ指向のコードを簡単に想像できます(これはあなたが暗示しているように感じました)。

だから、本当の質問は MVCパターンを使用する場合、手続き型コードを使用する傾向がありますか。

(そして、たぶん私はちょうど下票を得ますか?)


-1

アンチではありませんが、MVCにはOOPも必要ありません。

通常、クラスによって表されるコントローラーはデータを保持しないためです。純粋な機能で十分です。

さらに進んでデータを振る舞いから分離すると、たとえば、モデルがデータベースデータでのみ機能し、関数(データ操作を担当する)が呼び出されるたびにフェッチされるとしましょう(インスタンスに何らかのデータを格納する代わりに)フィールド)-モデルについても同じことが言えます。

さらに進むと、アプリケーションのビューレイヤーを取得して同様の方法で分割すると、MVCはOOPとは無関係であるという結論に終わります。手順のみを使用すれば、苦労せずにMVC実装を完全に記述できます。 。


ハハ、事実に直面したときにa **で痛みを感じた人がいるようです。OOPを使用して独自のフレームワークを作成するのに手間がかかりすぎていますか?失われた時間に耐えられませんか?最も簡単な答えが最高です。
luke1985 14年

この答えになぜ投票権があるのか​​はわかりません。彼は、それらは関係がなく、「反」ではないと言っています。かなり正確に思えます。
mwilcox

-3

私の意見では、OOPには(データと動作)が1つのエンティティ(クラス)として成形されているため、凝集よりも結合効果が大きいという欠点があります。一方、MVCには、...(Bean、DAO、その他のロジッククラス)を含むモデル、コントロールの移動方法を指定するコントローラー、およびデータの表示方法を決定するビューが個別に指定されています。これに基づいて、プロジェクトが大きすぎて準備ができていなくても、OOPとは異なり、混在する以外の別のエンティティとして簡単に作成できます。この問題は、分割n征服戦略と同様に論理パターンで解決され、MVCはこれにほとんど従います。


これはあなたの意見だけですか、何らかの形でバックアップできますか?
グナット14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.