1

都市をモデル化するクラスがあるとしましょう。その特徴は次のとおりです。

  • コンストラクターで設定される、プライベートな "name" と "population" の 2 つのプロパティのみがあります。
  • これらのプロパティのゲッターはありますが、セッターはありません。

このクラスのユーザーにプロパティを設定させたくありません。パブリック .edit() メソッドを使用してもらいたいのです。

このメソッドは、都市と人口の新しい名前を入力するためのフォームを開く必要があります。つまり、ビューです。次に、ビューがある場合は、MVC パターンを実装したいので、コントローラーが .edit() 呼び出しを受け取り、ビューをレンダリングし、データを取得してビューに送信し、その状態を変更します。

しかし、そうすると、都市モデルのプロパティをプライベートからパブリックに変更する必要があります。したがって、ユーザーが私のクラスをインスタンス化した場合、そのユーザーはプロパティを直接変更できます。

というわけで、哲学的な質問: それはカプセル化を破っていませんか?

EDITそれをより明確にするために:

このcity_instance.edit()メソッドは、オブジェクトを変更する唯一の方法です。

その上、私の問題の一部は、モデルがオブジェクトであるという誤解から来ていることがわかります (php mvc フレームワークでそれを読むことができます)。実際には別の抽象化であり、ビジネス ロジックをグループ化するレイヤーです (ドメイン オブジェクト +私はもっ​​と多くのことを推測します)

4

2 に答える 2

3

免責事項:メソッドの実装を提案している場所がよくわからない.edit()ので、そこを少し明確にしていただければ助かります。

ここで最初に考慮すべきことは、質問の箇条書きリストでは、Cityインスタンスが不変オブジェクトのように機能することを暗示しているように見えることです。コンストラクターでインスタンス変数を受け取り、外部の誰もそれらを変更できないようにします。ただし、後で、インスタンスを視覚的に編集する方法を実際に作成したいと述べていCityます。この 2 つの要件は、正反対の関係にあるため、明らかに緊張関係を生み出します。

MVC アプローチを使用する場合、ビューをモデルから分離することにより、主に 2 つの選択肢があります。

  • オブジェクトを不変として扱いCity、フォームで値が変更されたときにインスタンスを編集する代わりに、元のオブジェクトを破棄して新しいオブジェクトを作成します。
  • 既存のCityインスタンスを変更する方法を提供します。

City最初のアプローチは、実際に aを不変オブジェクトと見なす場合、モデルをそのまま維持します。2 つ目については、さまざまな方法があります。

  • 最も標準的な方法は、Cityクラスでミューテーターを提供することです。.edit()これは、配列を取ることによって一度に多くのプロパティを変更するために、プロパティごとに独立したセッターの形をしたり、共通のメッセージ(これはあなたが言及した方法だと思います)を持つことができます。モデルはビューを認識する必要がないため、ここではフォーム オブジェクトをパラメーターとして使用しないことに注意してください。ビューにモデルの内部変更を記録させたい場合は、オブザーバーパターンを使用します。
  • コントローラーには「フレンド」クラスを使用します。一部の言語では、フレンド クラスがオブジェクトの内部にアクセスできます。この場合、モデルにミューテーターを追加しなくても、モデルとビューを接続できるモデルのフレンド クラスであるコントローラーを作成できます。
  • リフレクションを使用して、フレンド クラスと同様のことを行います。

この 3 つのアプローチのうち最初のアプローチは、言語に依存しない唯一の選択肢です。それがカプセル化を破るかどうかは、要件自体が矛盾するため、言うのは難しいです (基本的には、ユーザーが変更できるビューからモデルを分離したいが、モデル自体は許可しないことを意味します)外側に変更します)。ただし、変更可能なインスタンスが必要な場合は、モデルをビューから分離すると、明示的な変更メカニズムを持つことが促進されることに同意します。

HTH

于 2013-03-14T20:49:38.557 に答える
1

注:Webアプリケーションに適用されるMVCについて言及しています。MVCはさまざまな種類のアプリに適用でき、さまざまな方法で実装されているため、特定の実装ではなく、パターンによって定義されたものについて厳密に話しているのでない限り、MVCが特定のことを実行するかどうかを判断するのは非常に困難です。 。

あなたは「カプセル化」とは何かについて非常に具体的な見解を持っていると思います。その見解は、カプセル化の教科書の定義と一致せず、一般的な使用法とも一致しません。セッターがいないことを要求する「カプセル化」の定義はありません。実際、Setterはそれ自体がオブジェクトを「編集」するために使用されるメソッドであるため、一種のばかげた議論です。

ウィキペディアのエントリから(「ゲッターとセッターのように」と書かれているところに注意してください):

一般に、カプセル化はOOP(オブジェクト指向プログラミング)の4つの基本の1つです。カプセル化とは、クラス内の変数などを非表示にして、許可されていない第三者が使用するのを防ぐことです。したがって、getterやsetterなどのパブリックメソッドはそれにアクセスし、他のクラスはこれらのメソッドを呼び出してアクセスします。

http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)

さて、それはMVCがカプセル化を破らないということではありません。私は、カプセル化が何であるかについてのあなたの考えは非常に具体的であり、特に標準的ではないと言っているだけです。

確かに、ゲッターとセッターを使用すると、オブジェクト自体の外部で直接変更できるリストを返すなど、多くの問題が発生する可能性があります。データを非表示に保つために(気にする場合は)注意する必要があります。コレクションを別のコレクションに置き換えることもできますが、これはおそらく意図したものではありません。

デメテルの法則は、ここでは何よりも関連性があります。

しかし、これはすべて、とにかく本当にただの赤いニシンです。MVCはGUIに関するものであり、GUIは可能な限りシンプルにする必要があります。ビューにもコントローラーにもロジックがほとんどないはずです。単純なビューモデルを使用して、フォームデータを単純な構造に逆シリアル化する必要があります。これを使用して、任意のビジネスアーキテクチャに適用できます(セッターが必要ない場合は、必要のないオブジェクトを使用してビジネスレイヤーを作成します)。セッターを使用し、ミュータッターを使用します。)

UIレイヤーに複雑なアーキテクチャーはほとんど必要ありません。UIレイヤーは、HTTPのフラットな形式とコマンドの性質を、選択したビジネスオブジェクトモデルに変換する境界およびゲートウェイのようなものです。そのため、HTTPはそうではないため、UIレベルで純粋にOOになることはありません。

これはインピーダンスミスマッチと呼ばれ、オブジェクトモデルはリレーショナルモデルに簡単にマッピングできないため、ORMに関連付けられることがよくあります。HTTPtoBusinessオブジェクトについても同じことが言えます。その点で、MVCはORMの当然の結果と考えることができます。

于 2013-03-14T21:02:23.720 に答える