1. ホーム
  2. model-view-controller

[解決済み] 太ったモデルと痩せたコントローラーは、まるで神モデルを作っているようだ。

2023-01-04 17:44:14

質問

を提唱しているブログをよく見かけます。 太ったモデルや痩せたコントローラ アプローチ、特にRails陣営のものを多く読んでいます。その結果、ルータは基本的にどのコントローラでどのメソッドを呼び出すかだけを考え、コントローラのメソッドが行うことは、モデル上の対応するメソッドを呼び出してからビューを表示させるだけです。ですから、私はここで理解できない2つの懸念を抱いています。

  1. コントローラとルーターは、ルートに基づいて神のようなモデル上のメソッドを呼び出すだけで、実際にはあまり異なるタスクは行っていません。
  2. モデルがやりすぎている。メールの送信、リレーションの作成、他のモデルの削除と修正、タスクのキューイングなど。基本的に、モデリングやデータの処理に関係するかしないかわからないことをすべて行うことになっている、神のようなオブジェクトがあります。

どこで線引きするのでしょうか?これはまさに神のパターンに陥っているのではないでしょうか?

どう解決する?

<ブロッククオート

RailsをMVCデザインパターンの定番として見るのは、最良のアイデアではないかもしれません。このフレームワークは、いくつかの固有の欠点を持って作られています (私はこのことについて 別記事 で詳しく説明しました)、コミュニティは今ようやくその欠点に取り組み始めたところです。DataMapper2 を見てみましょう。 開発 を最初の大きな一歩として見ることができます。

いくつかの理論

このようなアドバイスをする人は、かなり一般的な誤解に悩まされているようです。そこで、まずその誤解を解くことから始めましょう。 モデルは、現代のMVCデザインパターンでは、クラスやオブジェクトではありません。 モデルはレイヤーです。

MVCパターンの背後にある核となる考え方は 懸念事項の分離 で、その最初のステップがプレゼンテーション層とモデル層の分割です。プレゼンテーション層がコントローラ(インスタンス、ユーザー入力の処理を担当)、ビュー(インスタンス、UI ロジックを担当)、テンプレート/レイアウトに分かれているように、モデル層もそうなっています。

モデル層が構成する主なパーツは、以下の通りです。

  • ドメインオブジェクト

    ドメインエンティティ、ビジネスオブジェクト、またはモデルオブジェクトとしても知られています (後者の名前は混乱を招くだけなので、私は好きではありません)。これらの構造は、人々が通常誤ってモデル (models") と呼ぶものです。これらはビジネスルール(ドメインロジックの特定のユニットのすべての計算と検証)を含む責任があります。

  • ストレージの抽象化です。

    通常 データマッパー パターンで実装されています。 ORMs と混同しないでください)。これらのインスタンスは通常、ドメインオブジェクトからの情報の保存と、ドメインオブジェクトへの情報の取り出しを任務とします。各ドメインオブジェクトは複数のマッパーを持つことができ、ちょうどストレージの形態(DB、キャッシュ、セッション、クッキー、/dev/null)がいくつかあるようなものです。

  • サービスです。

    アプリケーションロジック(つまり、ドメインオブジェクト間の相互作用、ドメインオブジェクトとストレージ抽象化間の相互作用)を担当する構造体です。これらはプレゼンテーション層がモデル層と相互作用するためのインターフェイスのように動作します。これは通常、Railsのようなコードではコントローラの中で終わるものです。

また、これらのグループの間のスペースに入るかもしれない構造物がいくつかあります。 DAOs , 作業単位 および リポジトリ .

ああ......そして、私たちが (ウェブの文脈で) ユーザー について話すとき、それは人間ではありません。ユーザーとは、実際には Web ブラウザのことです。

では、神々についてはどうでしょうか?

恐ろしくてモノリシックなモデルを扱う代わりに、コントローラはサービスと相互作用する必要があります。ユーザーの入力したデータを特定のサービス (例えば MailService または RecognitionService ). この方法では、コントローラはモデル層の状態を変更しますが、それは明確なAPIを使用し、内部構造をいじらずに行われます(これは抽象化の漏れを引き起こします)。

このような変更は、即座に何らかの反応を引き起こすか、ビューインスタンスがモデル層から要求するデータにのみ影響を与えるか、あるいはその両方が考えられます。

各サービスはドメインオブジェクトとストレージの抽象化された任意の数(通常はほんの一握りですが)と相互作用することができます。例えば RecogitionService は記事のためのストレージの抽象化について気にかけることはできません。

終了時の注意

このようにして、どのレベルでもユニットテストが可能で、(正しく実装されていれば)カップリングが低く、明確に理解できるアーキテクチャを持つアプリケーションを得ることができるのです。

しかし、心に留めておいてください。MVC は小さなアプリケーションのためにあるのではありません。もしあなたがMVCパターンを使ってゲストブックのページを書いているとしたら、それは間違ったやり方です。このパターンは 法律と秩序 を強制するためのものです。

<ブロッククオート

PHPを主要な言語として使っている人のために。 この記事 が適切かもしれません。モデル層についてのもう少し長い説明と、いくつかのコードの断片があります。