OOPの背後にある主な考え方は、単一のエンティティ(オブジェクト)でデータと動作を統合することです。手続き型プログラミングには、データと、データを変更する個別のアルゴリズムがあります。
Model-View-Controllerパターンでは、データとロジック/アルゴリズムはそれぞれ別個のエンティティ、モデル、コントローラーに配置されます。同等のOOPアプローチでは、モデルとコントローラーを同じ論理エンティティに配置するべきではありませんか?
OOPの背後にある主な考え方は、単一のエンティティ(オブジェクト)でデータと動作を統合することです。手続き型プログラミングには、データと、データを変更する個別のアルゴリズムがあります。
Model-View-Controllerパターンでは、データとロジック/アルゴリズムはそれぞれ別個のエンティティ、モデル、コントローラーに配置されます。同等のOOPアプローチでは、モデルとコントローラーを同じ論理エンティティに配置するべきではありませんか?
回答:
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
、それはビジネスロジックの一部だから?
Teller
に入りますがModel
、コントローラから呼び出すことができます。これはビジネスドメインの一部です。
MVC は単一のオブジェクトよりもはるかに高い抽象化レベルで動作し、実際、3つ(モデル、ビュー、コントローラー)のそれぞれは通常、それぞれデータと動作の両方を持つ多くのオブジェクトで構成されます。
データと動作をカプセル化するオブジェクトは、一般的なプログラムの優れた基本的な構成要素であるということは、すべての抽象化レベルであらゆる目的に最適なパターンであることを意味しません。
OOPは、それぞれが独自のデータと独自の動作を持つオブジェクト間の相互作用を制限しません。
アリとアリのコロニーの例えを考えてみましょう。個々のアリの行動(一日中走り回って餌を持ちます)は、コロニー全体の行動とは異なります(最も望ましい場所を見つけて、アリを増やします)。MVCパターンは、アリのコロニーの望ましい社会構造を記述し、OOPは個々のアリの設計をガイドします。
OOPは、関心の分離、つまり異なるオブジェクトの異なる役割/責任を分離することでもあります。
MVCは次のコンポーネントに分かれています。
したがって、これらの責任は明確に区別され、実際には複数のエンティティに分離する必要があります。
Model-View-Controllerパターンでは、データとロジック/アルゴリズムはそれぞれ別個のエンティティ、モデル、コントローラーに配置されます。
モデルとコントローラーは2つの異なる役割です。モデルには状態とロジックの両方があり、コントローラーには状態とロジックの両方があります。それらが通信するという事実は、いずれかのカプセル化を壊しません-コントローラーは、モデルがそのデータを保存する方法、またはコントローラーがその一部を取得または更新するときにデータに対して何を行うかを知りません。モデルは、モデルが提供するデータをコントローラーがどのように処理するかを知りません。
このように考えてください。オブジェクトがカプセル化を壊さずにデータをやり取りできなかった場合、実際には1つのオブジェクトしか持てません!
同等のOOPアプローチでは、モデルとコントローラーを同じ論理エンティティに配置するべきではありませんか?
MVC は OOPアプローチです。具体的には、オブジェクトを使用してプログラムを効果的に編成する方法を決定するためのレシピです。そしてノー、モデルとコントローラが同じエンティティであってはなりません。コントローラーにより、モデルとビューを分離できます。モデルとビューを互いに独立した状態に保つことで、テストと再利用の両方が可能になります。
MVCは、オブジェクトが相互作用する賢明な方法を記述するパターンです。それ自体はメタクラスではありません。OOとは、エンティティの動作とデータ、およびエンティティがどのように相互作用するかを記述することです。システム全体を1つの巨大なオブジェクトに統合することではありません。
モデル層は単なるデータではなく、コントローラー層は単なるロジックです。
コントローラ層には、その目的のためにオブジェクトの完全なコレクションがあります。ビューからの入力を受け取り、その入力をモデルが処理できるフォームに変換するためのオブジェクトがあります。Struts Javaフレームワークには、アクション/フォームモデルでこれの良い例があります。フォームにはユーザーからの入力が入力され、アクションに渡されます。アクションはそのデータを取得し、それを使用してモデルを操作します。
同様に、モデルレイヤーは完全にデータで構成されているわけではありません。たとえば、ユーザーオブジェクトを取得する-データベースからユーザーを取得するコード、またはユーザーを注文に関連付けるコード、またはユーザーの住所が会社のサービス地域内にあることを検証するコードが必要になる場合があります...画像。これはコントローラーロジックではありません。それはビジネスロジックであり、多くの場合、モデルレイヤーをビジネスロジック用のサービスまたはマネージャーレイヤー、データベースアクセス用のDAO(データベースアクセスオブジェクト)レイヤーなどの複数のレイヤーに分割しました。
MVCは、個々のモデル操作を整理する方法ではありません。それよりも高いレベルで動作します-アプリケーションへのアクセス方法を整理する方法です。ビューはデータとそれを操作するための人間のアクションを表示するためのものであり、コントローラーはユーザーアクションとさまざまなビューの間の変換のためのものであり、モデルはビジネスデータとそれが存在するビジネス上の理由が存在する場所です。
OOPのポイントは、一緒に属するデータと機能をグループ化することです。一部のデータに基づく計算は、必ずしもそのデータに属するとは限りません。
MVCでは、データ(ビュー)を表示する機能は、データ(モデル)とは別に保持されます。何故ですか?具体的には、基になるデータを変更せずに表示ロジックを変更できるようにします。同じデータの別のプレゼンテーションを作成する必要があるとき、またはディスプレイハードウェアの特性が変更されたとき、またはWindowsからLinuxに切り替えるときに、ビューを簡単に変更できます。または、2人が同じデータを見るための2つの異なる方法を使用したい場合。
MVCはOOPと競合していません。実際には、オブジェクト指向の原則の正しいアプリケーションから派生しています。
モデルオブジェクトにバインドされた永続データと、モデルがやり取りするデータベースからのアプリケーションデータを混同していると思います。モデルには、データベースを操作し、トランザクションを実行するためのビジネスロジックとルールが含まれます。今日のセールがあるか、ユーザーがVIPステータスの資格があるか、データにアクセス、設定、または操作するとき、または購入を実行するときにロジックをそれに応じて分岐するかどうかなど、内部状態フラグを設定およびチェックします。一連のメソッドと永続的な値またはデータのカプセル化の観点からオブジェクトについて説明するときに、これらのフラグについて話します。
モデルオブジェクトがどのビジネスルールが有効であるかを確立するためのデータを維持するのと同様に、コントローラーは、ユーザーがログインしているか、有効なクレジットを持っているかなど、アプリの動作に関連するより一般的なアプリケーション状態データを保持する必要があります所定の場所にカードデータ。モデルメソッドはそもそもこれらの状態を決定しますが、ビジネスの実行方法やデータトランザクションの実行方法に当てはまらない場合、コントローラーが一般的なアプリフローに関連するフラグを維持することは理にかなっています。ログインしていないと判断したら、別のログイン試行が行われることが明らかになるまで、モデルにユーザー状態チェックを行わないでください。
同様に、適切なビューオブジェクトと、ほとんどのサーバーサイドWebフレームワークで見られるより一般的なHTMLテンプレートを使用します。ユーザーの色設定が読み込まれると、そのデータを保持して実行するのはビューになります。設定の読み込み、検証、変更はすべてモデルの問題ですが、変更が発生するまでモデルの問題は1回だけである必要があります。
IMO、コントローラが内部集合オブジェクトとしてビューとモデルを備えた複合オブジェクトになれないということは何もありません。これは、UIウィジェットファクトリーのような小規模でMVCを適用する場合、実際には理にかなっています。コントローラーは、ビューとモデルの相互作用のデータとロジックの詳細を埋めながら、より高いレベルのアプリオブジェクトにインターフェイスを公開する理想的な場所だからです。ただし、コントローラーが実際に最高レベルのオブジェクトであるモノロシックアプリオブジェクトの場合は、実際には意味がありません。
私が理解したように。引数は、コンポーネントベースのアーキテクチャとOOPです。そして、宗教戦争に入ることなく、彼らは両方とも同じことを述べていると思います。さまざまな角度から見ているだけです。
たとえば、OOP / OODの重要なポイントは、コードをよりモジュール化して再利用可能にすることです。はい?
これがまさにコンポーネントベースのアーキテクチャの目標です。だから、彼らは何よりも似ています。
MVCはOOPの自然な進化であり、あえて言うと思います。オブジェクトの整理、懸念の分離、コードの再利用のためのより良い方法。
アンチではありませんが、MVCにはOOPも必要ありません。
通常、クラスによって表されるコントローラーはデータを保持しないためです。純粋な機能で十分です。
さらに進んでデータを振る舞いから分離すると、たとえば、モデルがデータベースデータでのみ機能し、関数(データ操作を担当する)が呼び出されるたびにフェッチされるとしましょう(インスタンスに何らかのデータを格納する代わりに)フィールド)-モデルについても同じことが言えます。
さらに進むと、アプリケーションのビューレイヤーを取得して同様の方法で分割すると、MVCはOOPとは無関係であるという結論に終わります。手順のみを使用すれば、苦労せずにMVC実装を完全に記述できます。 。
私の意見では、OOPには(データと動作)が1つのエンティティ(クラス)として成形されているため、凝集よりも結合効果が大きいという欠点があります。一方、MVCには、...(Bean、DAO、その他のロジッククラス)を含むモデル、コントロールの移動方法を指定するコントローラー、およびデータの表示方法を決定するビューが個別に指定されています。これに基づいて、プロジェクトが大きすぎて準備ができていなくても、OOPとは異なり、混在する以外の別のエンティティとして簡単に作成できます。この問題は、分割n征服戦略と同様に論理パターンで解決され、MVCはこれにほとんど従います。