web-dev-qa-db-ja.com

誰かがMVCを理解するのを手伝ってくれる?

MVCパターンに関するいくつかの記事を読んで、それが正確に何であるかを理解しようとしました。しかし、今までのところ、私が得るのは、モデル、ビュー、コントローラーの3つのモジュールを示す単純な図です。コードの再利用(DRY)を向上させるのに役立つと言う人もいますが、反対のことをすると思います。

現在、アプリケーションコードを異なるディレクトリに分割しています。1つは表示部分(プレゼンテーション:Html/Css/Js +クライアント側要求)用で、もう1つはコア関連機能用です。私はこのアプローチに不利な点をまだ見つけていません。多分私はまだ大きなアプリケーションを開発していないからかもしれません。小さな趣味のものだけです。

したがって、この分離とは別に、MVCで見つけたのはある種のURL書き換えであり、必要に応じて実現できると思います。何か足りないものはありますか?開発者がMVCパターンに非常に傾いている理由があるに違いありません。

10

Modelモデルは、モデル化しようとしているドメインを表し、アプリケーションのビジネスロジックもカプセル化します。たとえば、古き良きブログの例を使用して、ブログを構成するすべてのもの(投稿、コメント、タグ、カテゴリ、作成者、コメント者、編集者、フィードなど)について考えます。

これはあなたのドメインであり、アプリケーションで使用したいものに応じて、それらをMVCのMとしてモデル化します。たとえば、ユーザーが行う投稿を表すPostモデル、またはユーザーが行うコメントを表すCommentモデルを作成します。ほとんどのフレームワークでは、モデルが他のモデルと関係を持つことができます。たとえば、モデルは1つ以上の他のモデルを「所有」するか、1つ以上の他のモデルに同時に属するか、または両方を同時に所有できます。これらの関係は通常、次のように表されます。

  • 一対一
    • 2つのモデル間の1対1の関係の最も単純なタイプの関係は、1つのモデルがもう1つのモデルを所有していることを示しています。
  • 1対多
    • 作成者が投稿を作成するので、作成者モデルが多くの投稿モデルを所有していると考えることができます。これは、Authorモデルが関係のone側であり、Postモデルがmanyである1対多の関係として表されます。
  • 多対1
    • 上記の関係とは逆に、1つ以上のPostモデルが1つのAuthorモデルに属しています。ここでは、Postモデルは関係のmany側であり、Authorモデルはoneです。
  • 多対多
    • 場合によっては、多くのモデルを他の多くのモデルに所属させたり、所有させたりするシナリオがあります。ブログ投稿のタグについて考えてください。多くのタグを多くの投稿に関連付けることができます。したがって、Post/Tagモデルは互いに多対多の関係にあります。

モデルは、ビジネスロジックを適用する場所です。たとえば、作成者が投稿と共に画像をアップロードできるようにしたいが、特定のサイズ/サイズの画像のみが必要だとします。画像はPostモデルのプロパティであり、それに属しているため、画像ファイルのサイズをチェックしたり、サイズを変更したりするビジネスロジックは、Postモデルに組み込まれます。これは、モデルは太く、コントローラーは細いはずであるということになります。 MVCパターンを初めて使用する場合によくある間違いは、すべてのビジネスロジックをコントローラーに配置し、データベースの行を表すだけの空のモデルを作成することです(たとえば、モデルではなくコントローラーでイメージのサイズ変更ロジックを実行します)。

通常、データベースは ORM(Object Relational Mapper) を使用して操作します。 Ruby on Rails、Laravel、Symfonyなどの一般的なフレームワークを使用している場合、ORMは通常ActiveRecordパターンを使用します。 ActiveRecordは悪いパターンであると主張する人もいます。なぜなら、モデルは自分自身のデータベースと独自の内部ビジネスロジックに永続化する責任があるためです。モデルはデータベースに永続化する必要はありませんが、モデルがである場合、それらの値はデータベースのテーブルの行に格納されます。別の答えが示唆するように、それらは行でもデータベースでもありません。通常、モデルの値は1行だけに格納されますが、(本当にそうしたい場合は)異なるテーブルやデータベースの複数行に格納することもできます。他のフレームワークはこれを異なる方法で処理します。たとえば、ASP.NETのMVCモデルでは、データベースに自分自身を永続化する責任はありません。どちらが優れているかは議論の余地があります。私はRailsとASP.NET MVCの両方を使用しており、意味のある両方のアプローチに感謝しています(単純なモデルの単純なアプリケーションActiveRecordは素晴らしいです)。 ActiveRecordアプローチの主な問題は、モデルがデータベースに保存するテーブルと同じでなければならないことです。はるかに大きなテーブルがあり、そこからデータを抽出してモデルにマップする場合(既存のデータやレガシーデータを考えてください)、注意が必要です。

Viewビューは本質的にシンプルなので、理解するのが最も簡単な部分です。ほとんどのMVCフレームワークでの慣習では、ビューは愚かである必要があります。つまり、ビジネスロジックを実行するべきではありません(モデルによって実行されます、覚えていますか?)。コントローラーからデータを受け取り、ユーザーに見栄えのよい方法で表示するだけです。

ビューはビジネスロジックを実行するべきではありませんが、クライアントサイドロジックをそこに含めることができます。たとえば、投稿または作成者のリストを表示するビューがある場合、JavaScriptを使用して、ユーザーがリストの順序を動的に変更するなどのことができるようにします(アプリケーションに別のHTTPリクエストを行う必要はありません)。ポイントは、受け取ったデータに何らかの処理を適用できるということです。これは、データを変更するのではなく、別の方法でデータを表示することのみを目的とする必要があります。

Controllerコントローラは、アプリケーションをまとめる接着剤です。それらをオーケストラの指揮者のように考えてください。彼らは実際には楽器を演奏しませんが、オーケストラはそれらなしでは機能できません。あなたのコントローラーは同じです。ユーザーからの要求を解釈し、必要な操作を実行して目的の結果を生成します。

通常、ユーザーがURLを入力すると(posts/show/my-first-postとしましょう)、MVCフレームワーク(Rails/Laravel/ASP.NET MVC /何でも)には、URLを解析して決定するルーティングエンジンがあります。呼び出す正しいコントローラ。通常、URLはこれを容易にするある種の慣例に従います。 URLセグメントが{controller}/{action}/{id}に関連する規則を使用しているとします。最初のセグメントは呼び出すコントローラー、2番目のセグメントは使用するコントローラーのアクション、3番目のセグメントは(または、コントローラーに渡したい多くのパラメーター)は、パラメーターとしてそのコントローラーのアクションに渡されます。したがって、1つのパラメーターを受け取るpostアクションを持つshowコントローラーがある場合、idルーティングエンジンはそれにHTTPリクエストを渡します。

通常、コントローラーはモデル(ビジネスロジックを実行して結果を返す)を呼び出し、その結果をユーザーに表示するビューに(Webページの形式で)渡します。

10
Iain

例を挙げて説明します。

友達のリストを表示するWebサイトを作成するとします。だからそれはあなたの友達のリスト(A、B、C ..)から始まります。いずれかを選択すると、友達(A1、A2など)のリストが表示されます。

「ビュー」は、ユーザーが見ることができるものの実装です。この場合、必要なビューは1つだけです。つまり、人々のリストを表示するテーブルです。この見解では、これらの人々が誰であるか、どこから来たのか、どのように関係しているのかは関係ありません。人のリストを表示し、ユーザーのアクション(クリックなど)をコントローラーに中継するだけです。

モデルには、人とその関係のリストがあります。それらをどのように処理するか、またはビューに対するアクションがそれらにどのように影響するかはわかりません。それは単に人々のリストを持っています。

「人々のリストを取り、それを表示するためにビューに渡す」ことが、コントローラーの仕事です。ユーザーが人物をクリックすると、ビューはそのアクションをコントローラーに中継し、コントローラーはこの人物の関係をモデルで調べて、新しい人物リストを抽出し、それをビューに表示して表示します。など。

この種のアーキテクチャが大規模なプロジェクトにどのように役立つかをご覧いただければ幸いです。コードを大幅に簡素化し、再利用性を高め(同じビューを使用して「人」オブジェクトのリストを表示できます)、プロジェクトの1つの側面(データまたはUI)を他に影響を与えることなく簡単に変更できます。

12
user1349663

アイデアは、ビジネスロジックとUIを明確に分離することです。

モデルは、アプリケーションのデータとビジネスロジックです。ビューはUIロジックであり、モデルの視覚的表現を作成します。コントローラーは、2つの間を仲介して、それらを疎結合に保ちます。

以下は、理解を助けるための例です。これは、Web MVCではなくデスクトップMVCに関連していますが、一般的な考え方は同じです。

テキスト処理アプリケーションを想像してみてください。ユーザーがテキストを選択して「太字」ボタンを押したところです。

ビューはボタンが押されたことを認識していますが、このイベントの処理方法を認識していません(認識すべきではありません)。そのため、コントローラーに通知します(例:controller.boldPressed())。

コントローラは、これがモデルにとって何を意味するかを「認識」しています。これは単にmodel.makeTextBold()を実行することを意味する場合もあれば、最初にビューから選択されたテキストをフェッチし、次にモデルに対していくつかのメソッド呼び出しを行うなど、より複雑なことを意味する場合もあります。

次に、モデルはコントローラーからメソッド呼び出しを受け取り、必要なアクションを実行します。つまり、テキストを太字にします。 テキストはモデル内に保持されます-これはデータが保持される場所です。 ビューは、このデータの視覚表現、つまりモデルの視覚表現です。

最後のステップで、ビューはモデルの状態が変化したことを通知され、それ自体を更新できます(モデルの視覚的表現です)。多くの場合、これはObserverパターンを介して行われます(これに慣れていない場合は、パターンを学習してください)。または、コントローラーで行うこともできます。

ビューはモデルが変更されたことを通知され、それ自体を更新します。そして、私たちはいくつかの太字のテキストを得ました。

これがアイデアです。ご覧のとおり、ビューはモデルの動作について何も認識していません。さらに重要なことに、モデルはビューについて何も認識していません。このルーズカップリングにより、UIイベントハンドラーにビジネスロジックがなく、ビジネスロジックのUIに関する詳しい知識がないため、管理が容易になります。また、システムの他の部分への最小限の変更で、さまざまなビューまたはモデルを置き換えることができることを意味することもあります。

最後にもう1つあります。コントローラが不必要に感じる場合があることに注意してください。コントローラが行うのは、モデルへのメソッド呼び出しの受け渡しだけです。小さなアプリケーションでは、これはよくあるケースです。ただし、アプリケーションが大きくなる場合に備えて、この分離層を用意しておくのは良いことです。

お役に立てれば。

2
Aviv Cohn

私はこれについて一度学びましたが、本からではありませんでした。しかし、うまくいけば、これは不正確ではありません。

MVCはモデル、ビュー、コントローラーの略です。

ビューはGUIです

モデルはほとんどのプログラムであり、コントローラーはモデルとGUI /ビューの間のインターフェースとなるプログラムの一部です。

そのメリットは、たとえば要件に突然変更があり、新しいGUIが必要な場合は、プログラムをそれらのコンポーネントに分離したときに、1つのコンポーネントを変更するだけで済みます。プログラムのモデル部分を書き直したり修正したりする必要はありません。 (おそらく、コントローラーには少し修正が必要ですが、それほど必要ではありません)。そして、ビューの部分を書くことに集中します。したがって、プログラムは異なるビューを持つように構築されています。

さらに、データの格納方法の点でプログラムを異なる方法で構成する必要がある場合は、GUIを説明するコードを書き直す必要はありません。

0
barlop