0

私はこれまでの開発中に、このことについてしばらく考えてきました。

私はそのようなことをすることに反対しています。通常、ロジックを明示的に処理する別のメソッドを宣言しています。

例えば

クラスにオブジェクトのリストを返すメソッドがある場合、getter メソッドを介してこのコレクションを直接変更するのは悪い考えだと思います。

 Public Class ReportGenerator{

    private List<Configurations> configurations;

    List<Configuration> getConfigurations (){
      return this.configurations;
    }

    }

次のことを行うことは悪い習慣だと思います:

getConfigurations().remove(1); //remove a configuration via a getter

次のアプローチを使用します。

 Public Class ReportGenerator{

            private List<Configurations> configurations;

          public  List<Configuration> getConfigurations (){
              return Collections.unmodifiableList(this.configurations);
            }


          public void removeConfiguration(int index) //logic explicitly handle the remove
              { 
              this.configurations.remove(index);
            }

          }

ただし、もう1つ頭に浮かぶのは、構成オブジェクトにもゲッターとセッターがある場合、他の人を防ぐことはできないということです

  reportGenerator.getConfigurations().get(0).settTitle("test");

ReportGenerator の getter メソッドを使用して Configuration オブジェクトの状態を変更することはできますが、これは許可すべきではないと思います。しかし、これを防ぎたい場合は、ReportGenerator クラスでさらに多くのメソッドを宣言して、呼び出しを Configuration オブジェクトに転送し、防御コピーを使用する必要があります。

私の質問は、コンポジションを使用して別のオブジェクト B を含むオブジェクト A があり、両方にゲッターとセッターがある場合、A のゲッター メソッドを介してオブジェクト B の状態を変更することを好みますか? 例えば

A.getB().setTitle("");

または、B の状態を変更するために A にメソッドを追加することを好みますか (基本的に B への呼び出しを転送します)

例えば

A.setBTitle("");

このメソッドの内部では、A call B.setTitle("");

長い質問で申し訳ありませんが、正確に何を聞きたいのかよくわからないと思います。あなたが理解することを願って。:P

4

3 に答える 3

1

それは小さなクラスではうまくいくかもしれませんが、より複雑なオブジェクト階層をどのように維持しなければならないかについては身震いするでしょう. A突然いくつかのオブジェクトがフィールドになったと想像してください。それらのそれぞれの周りにラッパーを正しくするのは良い考えだと思いますか? そして、各オブジェクトがより複雑になるにつれて、そうすることを考えてみてください。場合によっては、 which calls which calls をA.getB().getC().setThingamabob()記述するよりも実行する方が簡単です。A.setSomething()B.setCField()C.setThingamabob()

オブジェクトが変更可能であってはならないと思われる場合は、setter を削除してください。のコンシューマーをまったくA変更する必要がない場合Bは、getB()メソッドを提供せず、代わりに に似たものを提供しますA.setThingy()。ここでは、設定されているものはすべて の一部であるとは言及されていませんB

API コントラクトは、クラスがそのすべてのプロパティにゲッター/セッターを提供する必要があることを必ずしも意味しません。プロパティが消費者によって直接読み取られたり変更されたりすることを意図していない場合は、その方法を提供しないでください。

于 2013-05-19T04:46:29.110 に答える
0

コードを書くときは、何よりも明確さが重要です。インスタンスの状態を変更することさえできますが、可能であればそうすることは控えます。適切なケースがない限り、つまり、遅延初期化 (最初にアクセスしたときにオブジェクトまたは値を作成する) を使用する場合を除きます。

最終的には依存しますが、ゲッターでオブジェクトの状態を変更しないようにします。

他の方もそう思っているようです

.. プロパティ ゲッター アクセスでオブジェクトの状態 (初期化など) を変更できるのはいつですか?

于 2013-05-19T04:30:52.070 に答える
0

それが悪い習慣かどうかの答えは、「場合による」です。

一方では、内部状態への参照を返すクラスは「漏れやすい抽象化」です。これは、いくつかの理論的な理由から好ましくありません。

  • API でクラスの実装の詳細を明らかにすると、それらの詳細への依存が促進され、変更が難しくなります。(これはここでは断固として問題ではありませんが、getter によって返されたものを変更することが物事を変更する標準的な方法になるように API を設計すると、これに対処するのが難しくなる可能性があります ...)

  • 詳細が不変のデータ構造として公開されている場合でも、クライアントは「ライブ」の変更を見ることができます。これは、アプリケーションがマルチスレッドの場合に問題になる可能性があります。

  • 詳細が変更可能なデータ構造として明らかにされた場合、クライアントは、クラスが通常実行する仮想チェックなどをバイパスして、クラスの状態を直接変更できます。

  • 一部のコンテキストでクラスが「セキュリティに敏感」である場合、抽象化が漏れている場合にセキュリティを破るために、あらゆる種類の余分な「ベクトル」があります。

一方、抽象化を漏れないようにすることは、コストがかかる可能性があります。

  • 変更不可能なコレクション ラッパーを割り当てる必要があり、追加レベルのメソッド呼び出しが追加されます。

  • コピーを返すと、データをコピーする追加のオーバーヘッドが発生します。また、マルチスレッド環境では、コピーの作成中にソース データ構造をロックする必要がある場合があります。

最後に、API でクライアントが変更を行えるようにする必要がある場合、漏れやすい抽象化を介して変更を行うと、実際には API 設計がより単純になる可能性があります。リークの問題は、(たとえば) 関連するメソッドを「パッケージ プライベート」にすることで軽減できます。

要約すると、これは「優れた OO 設計」と実用的な問題との間のトレードオフです。これらをケースバイケースで比較検討する必要があります。


ところで、質問のタイトルと説明は誤解を招きます。例えば

  getConfigurations().remove(1); //remove a configuration via a getter

これは誤解を招きます。「ゲッターを介して」構成を削除していません。ゲッターから返されたオブジェクトを介して削除しています!!

(私はつまらないことを言っていますが、人々にあなたを理解してもらいたいのであれば、彼らが理解できる言葉を使う必要があります。)

于 2013-05-19T05:38:23.487 に答える