注: MVC および MVC にインスパイアされたパターンは高度な構造です。これらは、通常のオブジェクト指向 ( SOLIDおよびその他のガイドラインに従う) コードが管理不能になり始めるコードベースで使用されることを意図しています。このパターンを導入すると、追加の制約が課され、非常に複雑なアプリケーションを含めることができます。MVC は、"hello world" アプリ向けではありません。
最初から始めましょう...
MVC および MVC にインスパイアされたデザイン パターンの背後にあるコア アイデアは、関心の分離です。上記の分離は 2 重です。
- モデル レイヤーは UI レイヤーとは別のものです。
- ビューはコントローラーから分離されています

モデル層(「クラス」や「オブジェクト」ではない) には、いくつかの構造グループが含まれ、それぞれがビジネス ロジックの異なる側面として扱われます。主な部分は次のとおりです。
- ドメイン オブジェクト: 検証、ビジネス ルール
- ストレージの抽象化: ドメイン オブジェクトからのデータの永続化とキャッシュ
- サービス: アプリケーション ロジック
また、リポジトリ、作業単位などが混在している可能性があります。
UI レイヤーは、主にビューとコントローラーで構成されます。ただし、どちらもサービスを利用してモデル層とやり取りします。サービスは、コントローラーがモデル レイヤーの状態を変更し、ビューがその新しい状態に基づいて情報を収集する方法を提供します。
Web のコンテキストでは、Web アプリケーションが示す要求と応答の性質のために、ビューとコントローラーは緩いペアを形成します。
コントローラーは現在のビューの状態を直接変更できますが、これらの変更はモデルを通じて行われることがより一般的であることに注意してください。ビューを直接変更する理由の 1 つは、たとえば、XML の代わりに JSON で応答する必要がある場合です。
また、出力形式ごとに異なるビューを簡単にインスタンス化し、ポリモーフィズムを利用できると主張することもできます。
ビューではないものは何ですか?
ビューは単に美化されたテンプレート ファイルであるという誤解が広まっています。この間違いは、RubyOnRails プロトタイピング フレームワークのリリース後に非常に一般的になりました。
ビューはテンプレートではありません。それらをそのまま使用すると、MVC および MVC にインスパイアされたパターンの背後にあるコア原則を破ることになります。
テンプレートがビューであると仮定すると、アーキテクチャに大きな影響を与えます。ビューにはプレゼンテーション ロジックを配置する場所がないため、コントローラーまたはモデル レイヤーのいずれかにプレゼンテーション ロジックをプッシュします。ほとんどの人は、プレゼンテーション ロジックがモデル レイヤーに存在しないことを理解しているため、通常は "コントローラー" を選択します。
基本的に、これによりビューとコントローラーがマージされます。
ビューは何をしていますか?
ビューの役割は、プレゼンテーション ロジックを処理することです。Web のコンテキストでは、ビューの目標はユーザーへの応答を生成することです(ちなみに、これは人間ではなくブラウザーです)。
技術的には、ユーザー Web ソケットがモデル層を監視するクライアント側のビューを作成することは可能ですが、実際には実装することは事実上不可能です。特にPHP環境ではありません。
この応答ビューを作成するには、モデル層から情報を取得し、収集されたデータに基づいて、データをテンプレートに配布してレンダリングするか、場合によっては単純に HTTP ロケーション ヘッダーを送信することによって、応答を組み立てます。
Post/Redirect/Getを使用する場合、リダイレクト部分は、よくあるコントローラーではなく、ビューによって実行されます。
非常に主観的なビット:
最近、次のアプローチを使用して MVC と対話することを好みました。
// the factory for services was injected in constructors
$controller->{ $method.$command }($request);
$response = $view->{ $command }();
$response->send();
は$method
現在のREQUEST_METHODであり、REST のような API を装うように調整されており、$command
人々が通常「アクション」と呼ぶものです。GET
コントローラーには、とPOST
(別の) 要求用の別個のルーチンがあります。if
これは、すべての「アクション」で同じものを避けるのに役立ちます。
ビューでは、同様の名前のメソッドを呼び出して、クライアントに送信される応答を準備します。
警告: このセットアップにはSRP違反が含まれていると思われます。それを自分のものとして採用するのは悪い考えかもしれません。
DRYはどうですか?
既にお気付きかもしれませんが、ビューをインスタンスとして持つことには若干の問題があります。コードの断片が繰り返されることになります。例: メニューまたはページネーション。
ページネーションを見てみましょう.. ページネーションにはロジックが含まれていますが、このロジックはモデルレイヤーとは関係ありません。モデルには「ページ」という概念がありません。代わりに、このビットのロジックは UI レイヤーに常駐します。しかし、各ビューにページネーションが含まれているか継承されている場合、それは明らかに SRP (および実際には他のいくつかの原則) に違反しています。
この問題を回避するために、ビューにプレゼンテーション オブジェクトを導入することができます (そしてそうすべきです)。
注: Fowler はそれらを「プレゼンテーション モデル」と呼んでいますが、私はその名前が「モデルとは何か」という全体的な混乱を助長していると思います。したがって、代わりに「プレゼンテーション オブジェクト」と呼ぶことをお勧めします。
プレゼンテーション オブジェクトは、繰り返されるロジックを処理します。これにより、ビューがはるかに「軽く」なり、一部の側面では、モデル層からのサービスの構造を反映し始めます。
プレゼンテーション オブジェクトとテンプレート間の相互作用は、ドメイン オブジェクトとデータ マッパー間の相互作用に似ています。
このすべてが常に必要ですか?
いいえ。この特定のアプローチは、UI レイヤーが非常に複雑なコードを対象としており、入力の処理をプレゼンテーションから分離する必要があります。
アプリケーションが .. emm .. のような非常にシンプルな UI を持っている場合、より大きな統合プロジェクト用の REST API を作成しています。そのような実用的なオプションは、すべてのコントローラーとビューのペアを単一のクラスにマージすることです。
また、従来のコードベースをリファクタリングする場合にも、この制約の少ないアプローチにより古いコードのチャンク全体を移動できるため、良いステップになる可能性があります。そのような古いコードの断片を分離し、すべてがまだ機能することを確認したら (レガシー コードにはテストがないため、それが「レガシー」になる方法です)、ビジネス ロジックの分離に集中しながら、さらに分割を開始できます。 UIから。
PS私自身は、ビューを処理する最善の方法を見つけるのにまだ苦労しています。この投稿は答えではなく、私の現在の理解のスナップショットのようなものです。