ゲッターの許可に関する正確な問題は何ですか?


15

私はセマンティクスについての意見を探しているのではなく、単にゲッターを賢明に使用することが実際の障害である場合を探しています。たぶん、それらに頼るという終わりのないスパイラルに私を投げ込むかもしれません、多分、代替案はよりきれいで、ゲッターを自動的に処理するなどです。具体的な何か。

私はすべての議論を聞いた、彼らはあなたがデータソースとしてオブジェクトを扱うことを余儀なくされるので、彼らが悪いと聞いた、彼らはオブジェクトの「純粋な状態」に違反しているたくさん受け入れる」。

しかし、a getDataが悪いものである理由はまったく理にかなったものではなく、実際には、セマンティクス、ゲッター自体は素晴らしいと主張する人もいますがgetX、名前を付けないでください、これは少なくとも面白いです。

私が賢明にゲッターを使用すると、そしてオブジェクトの完全性がそれを外に出しても壊れないデータのために、意見なしで壊れる1つのことは何ですか?

もちろん、何かを暗号化するために使用される文字列にゲッターを許可することは愚かなことではありませんが、システムが機能するために必要なデータについて話しているのです。たぶん、あなたのデータが通って引っ張られProviderたオブジェクトから、しかし、まだ、オブジェクトがまだ許可する必要がありProviderませんし$provider[$object]->getData、その周りに方法はありません。


なぜ私が求めているのですか:私にとって、ゲッターは賢明に使用され、「安全」として扱われるデータで神に送信され、私のゲッターの99%はオブジェクトを識別するために使用されますObject, what is your name? Object, what is your identifier?。プログラミングに関するほとんどすべてがアイデンティティであり、オブジェクト自体よりもそれが何であるかをよく知っている人がいるので、オブジェクトを扱う人はオブジェクトに関するこれらのことを知っているはずです。あなたが純粋主義者でない限り、私は本当の問題を見ることはできません。

「なぜゲッター/セッター」が悪いのかに関するStackOverflowの質問をすべて見てきました。99%のケースでセッターが本当に悪いことに同意しますが、ゲッターは韻を踏むだけで同じように扱われる必要はありません。

セッターはオブジェクトのIDを危険にさらし、誰がデータを変更しているかをデバッグするのを非常に難しくしますが、ゲッターは何もしません。


2
私のアドバイスは、オブジェクト指向理論の大部分を忘れています。練習。たくさんのコードを書いて、それを保守してください。何がうまく機能し、何が実際に何かをしてから数か月後に元に戻ることで何がうまくいかないかについて、はるかに多くを学びます。
jpmc26

1
@ jpmc26どういうことか…。私は誰も実際にOOPを正しく実行していないことに気づきませんでした。オブジェクトのフィールドに厳密に関係するカプセル化の概念は常にありましたが、オブジェクト自体は状態であり、自由に共有。本当に誰もがOOPを間違っているのです。そうではなく、パラダイムがオブジェクトである場合、OOPは不可能です。私は、システムがどのように機能するかを厳密に表現するためにOOPを厳密に使用し、それを聖杯でも、固体としても決して扱いません。それらは、私の概念の(実装を通じて)合理的に十分に拡張されたものを定義するために主に使用する単なるツールです。これが正しいかどうかを読んでいますか?
coolpasta

2
--cont、私が書くほど、プログラミングは、コードベースについて他の人、そしてあなたに推論できるようにするために必要なだけ抽象化できることがすべてだということに気づきます。もちろん、これの技術的な側面は、適切なチェックを行い、正しいルールを設定することです。実際、他の人に自分のコードをより良く理解させることができれば誰でも勝ちます。それを読んでいる誰にとっても理にかなっていることを確認してから、インターフェースでオブジェクトを適切にセグメント化し、チェックし、それらを推論するのが簡単なときに他のパラダイムに切り替えることで失敗しないことを確認してください:柔軟です。
coolpasta

2
これは私にはストローマンのように思えます。実際に使用可能なコードを書いている真面目な開発者が、ゲッターを賢明に使用することは問題だと主張するとは思わない。質問は、ゲッターが賢明に使用できることを意味し、さらにゲッターが賢明である可能性があることを意味しています。ゲッターの賢明な使用はないと言う人を探していますか?しばらくお待ちください。
ジミージェームズ

2
@coolpastaそのとおりです。純粋なOOPかどうかはあまり気にしません。ちょうど良い。人間が理解できる壊れたコードか、解読不能なCPUを愛する完璧なコードのどちらかを選択してください。OOPは、一度に考えなければならないことの数を減らすときにのみ役立ちます。それが、単純な手順よりも好きな唯一の理由です。それなしでは、理由もなく複数のソースコードファイルをジャンプするだけです。
candied_orange

回答:


22

ゲッターなしでは良いコードを書くことはできません。

理由は、ゲッターがカプセル化を壊さないからではありません。それは、ゲッターが、操作するデータを使用してメソッドを配置するOOPをたどらないように人々を誘惑しないからではありません。彼らはします。いいえ、境界のためにゲッターが必要です。

メソッドの移動を妨げ、データの移動を余儀なくされる境界にぶつかると、カプセル化とメソッドが作用するデータを一緒に保持するというアイデアは単に機能しません。

本当に簡単です。境界がないときにゲッターを使用すると、実際のオブジェクトがなくなります。すべてが手続き型になり始めます。これは以前と同じように機能します。

真のOOPは、どこにでも広めることができるものではありません。これらの境界内でのみ機能します。

これらの境界線は非常に薄くありません。それらにはコードがあります。そのコードをOOPにすることはできません。機能することもできません。このコードは、厳しい現実に対処できるように、理想を取り除いたものではありません。

マイケル・フェッターズは、オレンジの部分を一緒に保持する白い結合組織にちなんで、このコードを筋膜と呼びました。

これはそれについて考える素晴らしい方法です。同じコードベースに両方の種類のコードを入れても大丈夫な理由を説明しています。この観点がなければ、多くの新しいプログラマーは理想に固執し、最初の境界に達したときに心を砕き、これらの理想をあきらめます。

理想は適切な場所でのみ機能します。どこでも動作しないという理由だけで、あきらめないでください。動作する場所で使用します。その場所は、筋膜が保護するジューシーな部分です。

境界の簡単な例はコレクションです。これは何かを保持しており、それが何であるかを知りません。コレクションデザイナは、保持するオブジェクトの動作機能を、保持するオブジェクトが分からないときに、どのようにしてコレクションに移動できますか?できません。あなたは境界に立ち向かっています。これが、コレクションにゲッターがある理由です。

知っていれば、その動作を移動でき、状態の移動を回避できます。知っているときは、すべきです。いつもわからない。

一部の人々は、これを実際的なものと呼んでいます。そしてそうです。しかし、なぜ実用的でなければならないのかを知ってうれしいです。


あなたはセマンティックな議論を聞きたくないと言い、どこにでも「賢明なゲッター」を置くことを主張しているようです。このアイデアに挑戦することを求めています。私はあなたがそれを組み立てた方法に問題があるという考えを示すことができると思います。しかし、私はそこにいたので、あなたがどこから来たのかも知っていると思います。

どこでもゲッターが必要な場合は、Pythonを見てください。プライベートキーワードはありません。しかし、PythonはOOPをうまく機能させます。どうやって?セマンティックトリックを使用します。彼らは、先頭に下線を付けて個人的なものを意味します。あなたがそうすることに責任を負うならば、あなたはそれから読むことさえ許されます。「私たちはみんな大人です」と彼らはよく言います。

それでは、JavaとC#のすべてにゲッターを置くことと、それとの違いは何ですか?申し訳ありませんが、セマンティクスです。Pythonは、従業員専用のドアの後ろで突っついていることを明確に示しています。すべてにゲッターを平手打ちすると、そのシグナルを失います。リフレクションを使用すると、とにかくプライベートを取り除いても、セマンティックシグナルを失うことはありません。ここで行われる構造的な議論はありません。

したがって、残されているのは、「従業員のみ」のサインをどこに掛けるかを決める仕事です。プライベートと見なすべきものは何ですか?それを「賢明なゲッター」と呼びます。私が言ったように、ゲッターの最良の正当化は、私たちを理想から遠ざける境界です。それはすべてのゲッターをもたらすべきではありません。ゲッターが発生する場合は、動作を保護できるジューシーなビットにさらに移動することを検討する必要があります。

この分離はいくつかの用語を生み出しました。データ転送オブジェクトまたはDTOは、動作を保持しません。唯一のメソッドは、ゲッターとセッター、時にはコンストラクターです。この名前は本当のオブジェクトではないため、残念です。ゲッターとセッターは、実際にはブレークポイントを設定する場所を提供するコードをデバッグするだけです。その必要がなければ、パブリックフィールドの山になります。C ++では、構造体と呼ばれていました。C ++クラスとの唯一の違いは、デフォルトに設定されていたことです。

DTOは境界壁を越えて投げることができ、他のメソッドを安全で素晴らしいジューシーな動作オブジェクトに保持できるので便利です。真のオブジェクト。違反するゲッターがないため、カプセル化されます。私のビヘイビアオブジェクトは、パラメータオブジェクトとして使用することでDTOを食べる場合があります。共有の可変状態を防ぐために防御的コピーを作成しなければならないこともあります。境界内のジューシーな部分の内側に可変DTOを分散させません。それらをカプセル化します。隠します。そして、ついに新しい境界にぶつかったとき、私は新しいDTOをスピンアップし、それを壁に投げて、他の誰かの問題にします。

しかし、アイデンティティを表現するゲッターを提供する必要があります。おめでとうございます、境界が見つかりました。エンティティには、参照を超えるアイデンティティがあります。つまり、メモリアドレスを超えています。そのため、どこかに保存する必要があります。そして、何かがそのアイデンティティによってこのものを参照できなければなりません。アイデンティティを表現するゲッターは完全に合理的です。そのゲッターを使用して、エンティティがそれ自体で行うことができる決定を行うコードの山はそうではありません。

結局のところ、間違っているのはゲッターの存在ではありません。パブリックフィールドよりもはるかに優れています。悪いのは、そうでないときにあなたがオブジェクト指向であるふりをするのに使われるときです。ゲッターは良いです。オブジェクト指向であることは良いことです。ゲッターはオブジェクト指向ではありません。ゲッターを使用して、オブジェクト指向の安全な場所を切り分けます。


これがまさに私が尋ねた理由であり、私の会話がロバートと目に見えるかどうかはわかりません。私はセッターに同意ません。少なくとも自分にとっては、所有権をこのようなアクションに帰属させるのは非常に難しいため、以前はすべてでセッターを使用していました。私...私はすべてを書き直さなければなりませんでした。ゲッターの賢明な使用は、長い間徹底的なテストを行った後、純粋主義者でない場合には深刻なマイナス面はありません。
coolpasta

1
@coolpastaでは、データ所有者オブジェクトを作成できます。データ所有者オブジェクトはデータオブジェクトですが、データを(明確に)所有するように設計され、名前が付けられています。もちろん、これらのオブジェクトにはゲッターがあります。
-rwong

1
@rwongどういう意味clearlyですか?値によって何かからデータが渡された場合、明らかに、私のオブジェクトはデータを所有しますが、セマンティクスによって、この時点ではまだ他の人からデータを取得していません。次に、そのデータを変換して独自のデータに変換する操作を実行する必要があります。データに触れた瞬間に、セマンティックの変更を行う必要があり$data_from_requestます。名前を付けてください$changed_data。このデータを他の人に公開したいですか?getterを作成するとgetChangedRequestData、所有権が明確に設定されます。またはそれは?
coolpasta

1
「ゲッターなしでは良いコードを書くことはできません。」境界が本質的にゲッターを必要とするという考え方と同様に、これはまったく間違っています。これはプラグマティズムではなく、怠です。フェンスを越えてデータを投げてそれを行うのはかなり簡単です。ユースケースについて考え、優れた行動APIを設計するの難しいです。
ロバートブラウティガム

2
素晴らしい答えです!
cmaster-モニカを

10

ゲッターはハリウッドの原則に違反しています(「電話しないで、電話します」)

Hollywood Principle(別名Inversion of Control)では、物事を成し遂げるためにライブラリコードを呼び出す必要はありません。むしろ、フレームワークはコードを呼び出します。フレームワークは物事を制御するため、その内部状態をクライアントにブロードキャストする必要はありません。知る必要はありません。

最もinな形式では、ハリウッド原則に違反することは、ゲッターを使用してクラスの状態に関する情報を取得し、取得した値に基づいてそのクラスで呼び出すメソッドを決定することを意味します。最高のカプセル化違反です。

ゲッターを使用するということは、実際には必要ないのに、その値が必要であることを意味します

実際にパフォーマンスの改善が必要になる場合があります

最大のパフォーマンスを実現する必要がある軽量オブジェクトの極端な場合、ゲッターが課す非常に小さなパフォーマンスのペナルティを支払うことができない可能性が非常に低いです。これは、99.9%の時間では発生しません。


1
理解する必要はないので、理解して、あなたの真実で飛びます。しかし、私は必要な場所に到達しました。私が持っているGeneratorすべての私をループオブジェクトItems呼び出して、その後、オブジェクトgetNameごとにItemさらに何かをします。これの問題は何ですか?次に、見返りに、Generatorフォーマットされた文字列を吐き出します。これは私のフレームワーク内にあり、その上に、ユーザーがフレームワークに触れずにユーザーが提供するものを実行するために使用できるAPIがあります。
coolpasta

3
What is the issue with this?私が見ることができるものはありません。それは基本的にmap関数が行うことです。しかし、それはあなたが尋ねた質問ではありません。あなたは本質的に「ゲッターがお勧めできない条件はありますか」と尋ねました。私は2つと答えましたが、それはあなたがセッターを完全に放棄するという意味ではありません。
ロバートハーヴェイ

1
あなたは間違った人にその質問をしている。私はプラグマティストです。私は自分の特定のプログラムに最適なものを何でもします。そして、私の目的にかなうものでない限り、「原則」に多くの在庫を置きません。
ロバートハーヴェイ

2
@ jpmc26:フレームワーク。 ライブラリではありません。
ロバートハーヴェイ

2
フレームワークは、汎用言語をドメイン固有の言語に変換する試みです。ライブラリは、再利用可能なアルゴリズムのコレクションです。どちらかが依存するように求めます。依存関係をハードコーディングするか、依存関係を簡単に置き換えられるようにするかどうかはあなた次第です。
candied_orange

2

Getters Leak Implementation DetailsおよびBreak Abstraction

検討する public int millisecondsSince1970()

あなたのクライアントは、「ああ、これはint型である」、それがあると仮定して無数の呼び出しがあるだろうと思われますint型あなたが必要なことを実現すると...など、日付を比較する整数演算を行って、長いを、たくさんあるだろう問題のあるレガシーコードの Javaの世界では@deprecated、APIに追加すると、誰もがAPIを無視し、陳腐なバグのあるコードを維持し続けることになります。:-((他の言語も似ていると思います!)

この特定のケースでは、より良いオプションが何であるかはわかりません。@ candiedorangeの答えは完全に適切です。ゲッターが必要な場合は何度もありますが、この例は欠点を示しています。すべてのパブリックゲッターは、特定の実装に「ロック」する傾向があります。「境界を越える」必要がある場合に使用しますが、使用はできるだけ少なく、注意して先を見越してください。


これは本当ですが、データ型/構造をオブジェクトの変数に強制するためのパターンソリューションと、その変数のゲッターを使用するものには何がありますか?
coolpasta

1
この例は、別の現象である原始的な強迫観念を示しています。現在、ほとんどのライブラリとフレームワークにはtimepointtimespanそれぞれを表すクラスがあります。(epoch特定の値であるtimepoint。)これらのクラスには、彼らのようなゲッター提供getIntまたはgetLongまたはgetDouble。時間を操作するクラスが、(1)時間関連の算術をこれらのオブジェクトとメソッドに委任し、(2)ゲッターを介してこれらの時間オブジェクトへのアクセスを提供するように記述されている場合、ゲッターを取り除く必要なく、問題は解決されます。
-rwong

1
要約すると、ゲッターはAPIの一部であるため、ゲッターは過去、現在、未来を含むすべての結果を十分に考慮して設計する必要があります。しかし、それはゲッターの数を回避または最小化するという結論には至りません。実際、ゲッターが省略された特定の情報にアクセスする必要がある場合、ライブラリ側のAPIの変更とコードの変更が必要になります。したがって、特定のゲッターを実装または回避するかどうかの決定は、予防的な理由ではなく、ドメインと意図に基づいて行う必要があります。
-rwong

1
「millisecondsSince1970」は、1970年1月末までに32ビット整数で動作しなくなったため、それを使用するコードが多くなるとは思わない:-)
gnasher729

1
@rwongやや正しいが、タイムポイントを表す優先ライブラリーは安定していると仮定します。彼らはそうではありません。例えば、moment.js
user949300

1

最初の鍵は絶対が常に間違っていることを覚えていることだと思います。

単に人々の連絡先情報を保存するアドレス帳プログラムを検討してください。しかし、それを正しく行い、コントローラー/サービス/リポジトリー層に分割しましょう。

Person名前、住所、電話番号などの実際のデータを保持するクラスがAddressありPhone、クラスでもあるため、後でポリモーフィズムを使用して米国以外のスキームをサポートできます。これらの3つのクラスはすべてデータ転送オブジェクトなので、それらはゲッターとセッター以外の何でもありません。そして、それは理にかなっています:それらは、オーバーライドequalsgetHashcode; を超えてロジックを持ちません。完全な人の情報の表現を提供するように彼らに求めることは意味がありません:HTMLプレゼンテーション、カスタムGUIアプリ、コンソールアプリ、HTTPエンドポイントなどのためですか?

そこで、コントローラ、サービス、リポジトリが登場します。依存性注入のおかげで、これらのクラスはすべて、ロジックが多く、ゲッターが軽くなります。

コントローラのようなメソッドを公開します注入されたサービスを、取得するために起こっているgetsave、どちらも(いくつかの合理的な引数を取る、例えば、。 get、名で検索郵便番号で検索、または単にすべてを取得するためにオーバーライドを持っているかもしれません。saveおそらくかかります単一Personで保存します)。コントローラーにはどのゲッターがありますか?具象クラスの名前を取得できるとロギングに役立ちますが、その中に挿入された状態以外の状態は保持されますか?

同様に、サービスレイヤーはリポジトリをインジェクトするため、実際にPersonsを取得および保持できます。また、いくつかの「ビジネスロジック」がある場合があります(たとえば、すべてのPersonオブジェクトに少なくとも1つのアドレスまたは電話が必要になる場合があります)数)。しかし、繰り返しますが、そのオブジェクトには、注入されたもの以外の状態がありますか?繰り返しますが、なし。

リポジトリ層は、物事がもう少し面白くなる場所です。例えば、保管場所への接続を確立します。ファイル、SQLデータベース、またはメモリ内ストア。ここでは、ファイル名またはSQL接続文字列を取得するゲッターを追加するのは魅力的ですが、それがクラスに注入された状態です。リポジトリには、データストアに正常に接続されているかどうかを通知するゲッターが必要ですか?まあ、多分、しかし、その情報は、リポジトリクラス自体の外でどのような用途に使われますか?リポジトリクラス自体は、必要に応じてデータストアへの再接続を試行できる必要があります。これは、isConnectedプロパティがすでに疑わしい値であることを示唆しています。さらに、isConnectedプロパティは、おそらく最も正しい必要がある場合にのみ間違っているでしょう:チェックisConnectedデータを取得/保存する前に、「実際の」呼び出しが行われたときにリポジトリがまだ接続されていることを保証しないため、どこかで例外処理の必要性がなくなりません(どこに行くべきかについての議論がありますこの質問の範囲)。

ユニットテストも考慮してください(ユニットテストを書いているのですか?):サービスは特定のクラスが注入されることを期待しているのではなく、インターフェースの具体的な実装が注入されていることを期待しています。これにより、サービスに注入されるリポジトリを交換するだけでデータを保存するアプリケーション全体を変更できます。また、モックリポジトリを挿入することにより、サービスを単体テストすることもできます。これは、クラスではなくインターフェイスの観点から考えることを意味します。リポジトリインターフェイスはゲッターを公開しますか?つまり、すべてのリポジトリに共通であり、リポジトリの外部で有用であり、リポジトリに挿入されない内部状態はありますか?私は自分のことを考えるのは難しいと思います。

TL; DR

結論として、データを持ち運ぶことを唯一の目的とするクラスは別として、スタック内にはゲッターを配置する場所がありません。状態は、作業クラスの外部に挿入されるか、無関係です。


この考え方は、C#プロパティの適切な使用に関する議論と非常によく似ています。要するに、プロパティ(getterのみまたはgetter-setter-pairである可能性がある)は、「設定するものが取得するものである」、「getterはほとんど副作用がない」など、特定の契約を維持することが期待されます。 「ゲッターはエラーをスローしないようにする必要があります」など。結論に反して、プロパティ(またはゲッター)として公開するのが有益なオブジェクト状態が多数あります。ここに引用するには例が多すぎます。
-rwong

2
@rwongいくつかの例を知りたいと思います。たとえば、あるチームによって実装された「通常の」「エンタープライズ」アプリケーションの場合です。また、簡単にするために、サードパーティが関与していないと仮定しましょう。カレンダー、ペットショップなど、必要なものをすべて完備したシステムです。
ロバートブラウティガム

1

私が賢明にゲッターを使用すると、そしてオブジェクトの完全性がそれを外に出しても壊れないデータのために、意見なしで壊れる1つのことは何ですか?

可変メンバー。

ゲッターを介して公開するオブジェクトに物のコレクションがある場合、コレクションに追加される間違ったものに関連するバグにさらされる可能性があります。

getterを介して公開している変更可能なオブジェクトがある場合、予期しない方法で変更されるオブジェクトの内部状態に自分自身を開放する可能性があります。

本当に悪い例は、現在の値を変更可能な参照として公開する1から100までカウントしているオブジェクトです。これにより、サードパーティのオブジェクトがCurrentの値を変更して、値が予想される範囲外になるようにすることができます。

これは主に、可変オブジェクトの公開に関する問題です。構造体または不変オブジェクトの公開は、それらの変更が代わりにコピーを変更するので、まったく問題ではありません(通常、構造体の場合は暗黙のコピーによって、不変オブジェクトの場合は明示的なコピーによって)。

違いを見やすくするメタファーを使用する。

花には、それについてユニークなものがたくさんあります。それは持っているColorとそれが花びら(NumPetals)の数を持っています。その花を観察していると、現実の世界では、その色をはっきりと見ることができます。その後、その色に基づいて決定を下すことができます。たとえば、色が黒の場合はガールフレンドに与えないで、色が赤の場合はガールフレンドに与えます。オブジェクトモデルでは、花の色が花オブジェクトのゲッターとして公開されます。私がその色を観察することは、実行するアクションにとって重要ですが、花のオブジェクトにはまったく影響しません。私はその花の色を変えることができないはずです。同様に、colorプロパティを非表示にすることは意味がありません。花は一般に、人々がその色を観察するのを妨げることはできません。

花を染める場合は、その花に対してReactToDye(Color dyeColor)メソッドを呼び出す必要があります。このメソッドは、内部ルールに従って花を変更します。その後、Colorプロパティを再度クエリし、ReactToDyeメソッドが呼び出された後のプロパティの変更に対応できます。Color花を直接修正することは私にとって間違っているでしょうし、もし可能なら抽象化が壊れてしまいます。

時々(あまり頻繁ではありませんが、言及する価値があるほど頻繁に)セッターは非常に有効なオブジェクト指向設計です。Customerオブジェクトがある場合、アドレスのセッターを公開することは非常に有効です。あなたがそれを呼ぶかsetAddress(string address)ChangeMyAddressBecauseIMoved(string newAddress)それとも単にstring Address { get; set; }セマンティクスの問題です。そのオブジェクトの内部状態を変更する必要があり、それを行う適切な方法は、そのオブジェクトの内部状態を設定することです。Customerが住んでいた住所の履歴記録が必要な場合でも、セッターを使用して内部状態を適切に変更することができます。この場合、Customer不変であることは意味がなく、アドレスを変更するためのセッターを提供するよりも良い方法はありません。

誰がゲッターとセッターが悪いか、オブジェクト指向のパラダイムを壊していると示唆しているのかわかりませんが、もしそうなら、彼らはたまたま使用する言語の特定の言語機能に応じてそうしているでしょう。これはJavaの「すべてがオブジェクトである」という文化から生まれた(そしておそらく他の言語にも拡張された)気がします。.NETの世界では、この議論はまったくありません。ゲッターとセッターは、その言語でアプリケーションを作成する人だけでなく、言語API自体でも使用される第一級の言語機能です。

ゲッターを使用するときは注意が必要です。間違ったデータを公開したり、間違った方法でデータを公開したりしたくない(つまり、可変オブジェクト、コンシューマが内部状態を変更できる構造体への参照)。ただし、オブジェクトをモデル化して、データがカプセル化され、オブジェクトが外部コンシューマーによって使用され、同じコンシューマーによる誤用から保護されるようにする必要があります。多くの場合、ゲッターが必要になります。

要約すると、ゲッターとセッターは有効なオブジェクト指向設計ツールです。それらは、すべての実装の詳細が公開されるほど自由に使用されるべきではありませんが、オブジェクトの消費者がオブジェクトを効率的に使用できないほど控えめに使用する必要もありません。


-1

ゲッターを使用すると壊れるのは、意見のない1つのことです...

保守性が壊れます。

いつでも(私はほとんど常に言うべきです)あなたは基本的にあなたから求められたよりも多くを与えるゲッターを提供します。これはまた、あなたが要求された以上のメンテナンスをしなければならないことを意味します。つまり、本当の理由もなくメンテナンス性を低下させます。

@candied_orangeのCollection例に行きましょう。彼が書くべきこととは反対にCollection すべきではない、ゲッターを。コレクションは非常に特定の理由で存在します。最も顕著なのは、すべてのアイテムを反復処理することです。この機能は誰にとっても驚くことではないので、この明らかなユースケースをユーザーにプッシュしたり、for-cyclesやgetterを使用したりする代わりに、に実装する必要Collectionあります。

公平を期すために、一部の境界にゲッター必要です。これは、それらが何に使用されるか本当にわからない場合に起こります。たとえば、Javaからプログラムでスタックトレースを取得できますExceptionクラスは、人々がライターが想像しなかった、または想像できなかっな奇妙な理由でを使用したかったためです。


1
反例。のCollectionように、2を同時に反復する必要がある関数を考えます(A1, B1), (A2, B2), ...。これには「zip」の実装が必要です。反復機能が2つのうちの1つに実装されている場合、どのように「zip」を実装しますCollectionか?
-rwong

@rwong Collectionzip、ライブラリの作成方法に応じて、自身で実装する必要があります。実装されていない場合は、実装し、ライブラリ作成者にプルリクエストを送信します。いくつかの境界は時々ゲッターを必要とすることに同意したことに注意してください、私の本当の問題はゲッターが最近どこにでもあるということです。
ロバートブラウティガム

その場合、それCollectionは、少なくともライブラリの独自の実装のために、ライブラリがオブジェクトにゲッターを持たなければならないことを意味しますzip。(つまり、ゲッターは少なくともパッケージの可視性を持っている必要があります。)そして今、あなたはあなたのプルリクエストを受け入れるライブラリ作成者に依存しています
...-rwong

よくわかりません。Collection明らかにそれ自身の内部状態にアクセスすることができ、または任意のより正確にはCollection、インスタンスが他の内部状態にアクセスすることができます。これは同じタイプで、ゲッターは必要ありません。
ロバートブラウティガム

私もあなたの話を聞いていますが、それではゲッターのより良い解決策は何ですか?私はそれが質問の範囲外であることを知っています。
coolpasta
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.