web-dev-qa-db-ja.com

MVCモデルを使用している場合でも、getter / setterによってカプセル化がどのように破壊されるか

Javaでのカプセル化について考えていたところ、ゲッター/セッターがカプセル化を解除する方法を考えました。 this を通過した後、ゲッター/セッターを回避するような多くの推奨事項を見ました不要なフィールド、またはそれらを実装する方法に関するいくつかのポリシー。

私が理解できなかったのは、MVCモデルの場合、ゲッター/セッターがカプセル化をどのように壊すかです。 MVCフレームワークの例を取り上げたい場合は、Spring-MVCを検討したいと思います。

したがって、基本的に、MVCではデータは通常、ビジネスコードによって操作され、インターフェイスを実装します。ビジネスコードはControllerから注文を取得していますが、Modelをまったく使用していません。

このようにして、モデルが2つのレイヤー(コントローラーとビジネス)にうまく分離または埋め込まれていることがわかります。 MVCモデルでもゲッターとセッターがカプセル化を解除する理由を誰かが私に説明できますか?.

私の質問が明確であることを望みます。不足しているものがあれば、お知らせください。ありがとうございました。

編集

おそらく人々は読んでおらず、ただフラグを立てているだけです。私の質問は、ゲッター/セッターが正当化される理由ではなく、主にMVCとカプセル化を扱います。私の焦点はまだMVCに残っているので、私は答えを受け入れていません。

3
We are Borg

簡単な答え:ゲッターメソッドとセッターメソッドを説明する方法で使用すると、問題が発生する可能性が高くなります。また、それらを削除しても具体的な問題は解決しません。

より長い答え

カプセル化は情報を隠すについてであることを覚えておいてください。正式には、必要なのはデータ構造-プライベートフィールド-だけですever一連の固定ルーチン-メソッドによってアクセスおよび変更されます。内部のデータ構造を変更したい場合は、プログラム全体ではなく、限られた一連のルーチンを実行するだけで更新できるため、メンテナンスが改善されます。利点は簡単にわかります:)。

実装情報を公開すると、get/setの問題が発生します。データベース接続を公開する例を見てみましょう。突然、オブジェクトがデータベースと通信することを世界に宣言しました。クライアントコードはその接続を使用して他のことを行います。 2年後、データベースを削除しました。もう必要ありません。しかし、クライアントコードは古いデータベースへの接続を期待しています!オブジェクトを好きなように変更することはできません。また、役に立たないジャンクを持ち歩かなければなりません。

ただし、別のケースでは、非表示にするものがありません。顧客はID、名前、電話番号です。それを隠さないでください、それはクライアントコードがまさに必要とするものです!アプリケーションの複数の部分でこれを実行する必要があります。UIはフォーマットされたバージョンをユーザーに表示し、データベースは値を保存して読み取り、JSONライブラリは情報をシリアル化して注文をサードパーティに送信します。 ビジネス情報です。役立つようにアクセスできる必要があります。その場合、ゲッター(おそらくセッター)は完全に有効です。

あなたの場合:ビジネスロジックのゲッターがモデルを隠す場合、それは完全に問題ありません。それらを使用してください。ゲッターのないデザインは、より良くないかもしれません。

最後の注記として:「教えてはいけないこと」と呼ばれるもののために、人々はしばしばゲッターに反対しています。これは、カプセル化とはまったく異なる問題です。これは設計哲学であり、その利点は情報を隠すよりも明確ではありません。後者は70年代にすでに知られていましたが、前者はより最近の発明です。 「Tell do n't ask」は、一部のアプリケーション、特にイベントドリブンアプリケーションでは素晴らしいです。悲しいかな、それはCRUDアプリケーションではうまく機能しません。CRUDアプリケーションでは、重要なのは情報について尋ねることです。 「聞かないでください」が解決する特定の一連の問題の外にいると想定して、罪のないゲッターを使用します。 実装を非表示にすることを忘れないでください

ゲッター/セッターはパブリック変数と同じデータを公開するという事実にそれらはそれらが単に変数のメソッド呼び出しラッパーであるためです。

一旦パブリック変数が悪い考えであることに人々が気づいたならば、それらは制約なしでオブジェクトの外部で修正されることができました。これに対する解決策は、すべてのメンバー変数をプライベートにし、それらに作用するメソッドを導入して、より詳細な制御を可能にし、クラスが何をするように設計されているか(つまり、それを行う方法ではなく)意味のあるインターフェースを公開することです。

しかし、残念ながら、プロパティの構文糖は、区別を曖昧にするために導入されました。つまり、クラス変数の一部であるかのように見える変数にアクセスできるメソッドがあり、それらは明らかにパブリック変数の同等のメソッドにすぎませんアクセス。

例として、あなたの年齢を保持するPersonクラスを想像してください。これをメンバー変数に設定して、それがパブリック変数である場合、呼び出し元が_p.age = 20;_を設定できるようにすることができます。または、プロパティを設定すると、代わりにp.age_set(20);になります(事実上、変数割り当てのように見えるようにするために、構文糖が存在することはわかっています)。または、ageメンバー変数を無視して、誕生年を計算して変数に格納するp.Age(20);を使用することもできます。

この後者はカプセル化を維持しています-呼び出し元はpersonオブジェクトがどのようにあなたの年齢を追跡するのかを知りません、または気にしません。データを設定およびフェッチする方法があることだけです。構造体とクラスの設計の違い(または動作主導ではなくデータ主導の設計。後者は保守とシステムの使用にはるかに優れています)

2
gbjbaanb