JavaRush /Java Blog /Random-JA /ゲッター/セッター。悪。そして期間
angelina
レベル 5

ゲッター/セッター。悪。そして期間

Random-JA グループに公開済み
Egor Bugaenko による記事、2014 年 9 月 19 日 | この古い議論 ゲッター/セッター。 悪。 そしてポイント-1は、2003 年に Allen Holub によって有名な記事「なぜゲッター メソッドとセッター メソッドは邪悪なのか- ゲッター/セッターはアンチパターンなのか、避けるべきなのか、それとも何かあるのか」で始まったものです。オブジェクト指向プログラミングでは必ず必要になります。この議論に私の 2 セントを追加さ​​せていただきます。以下のテキストの要点は次のとおりです: ゲッターとセッターは悪い習慣であり、それらを使用する人には言い訳の余地がありません。ただし、誤解を避けるためにもう一度言いますが、私は get/set の使用を可能な限り避けるべきだと言っているわけではありません。いいえ。コードに彼らを近づけさせなかったと言っているのです。 ゲッター/セッター。 悪。 そしてポイント-2この発言についてどう思いますか? 注目に値しますか? あなたは get/set パターンを 15 年間使用していて、尊敬される Java アーキテクトですか? そして、見知らぬ人のこんなくだらない話を聞きたくもありませんか?まあ…あなたの気持ちはわかります。私も、David West の『オブジェクト思考』という本に出会うまで、同じように感じていました。これは、私が今まで読んだオブジェクト指向プログラミングに関する最高の本です。だからお願い。落ち着いて、私が説明しようとしていることを理解してください。 論争の対象 オブジェクト指向の世界では、「アクセサ」(ゲッターとセッターの別名) に対していくつかの議論があります。そしてそれらはすべて非常に正しい議論です。それらを簡単に見てみましょう。 Ask, Don't Tell : Allen Holub は、「仕事をするために必要な情報を尋ねるのではなく、その情報を持っている組織に仕事をしてくれるよう『依頼』してください」と言います。 カプセル化原則の違反: オブジェクトは、セッターを介してオブジェクトに任意のデータを埋め込むことができるため、他のオブジェクトによって分解される可能性があります。誰でもその状態を変更できるため、オブジェクトはそれ自身の状態を十分に安全にカプセル化することができません。 実装の詳細が明らかに: あるオブジェクトを別のオブジェクトから取得できる場合、最初のオブジェクトの実装の詳細に過度に依存していることになります。明日変更された場合 (たとえば、結果の型)、コードを変更する必要があります。上記の正当化はすべて確かに理にかなっていますが、これは最も重要な点を見逃しています。 基本的な誤解 ほとんどのプログラマーは、オブジェクトはメソッドを備えたデータ構造であると信じています。Bozhidar Bozhanov の記事を引用します:ゲッターとセッターは悪ではありません。ただし、ゲッターとセッターが作成されるほとんどのオブジェクトにはデータが含まれているだけです。この誤解は大きな誤解の結果です。オブジェクトは「データを保存するだけ」ではありません。オブジェクトは、メソッドが付加されたデータ構造ではありません。この「データ ストレージ」の概念は、オブジェクト指向プログラミングと手続き型言語、特に C と COBOL から生まれました。もう一度繰り返しますが、オブジェクトは、データ要素とそれらを操作する関数の単なるコレクションではありません。オブジェクトはデータ オブジェクトではありません。じゃあ何? ボールと犬 真のオブジェクト指向プログラミングでは、オブジェクトはあなたや私と同じように生き物です。これらは、独自の行動、特性、ライフサイクルを持つ生物です。生物はセッターを持つことができますか? 犬にボールを付ける(「セット」する)ことはできますか?考えないでください。しかし、それはまさに以下のコード部分が行うことです。
Dog dog = new Dog();
dog.setBall(new Ball());
それで、どうですか?あなたは犬からボールを​​取り出すことができますか? まあ、それができると仮定しましょう。彼女がそれを食べて、あなたが彼女に手術をした場合に備えて。この場合、はい、犬からボールを​​受け取る(「ゲット」する)ことができます。これはまさに私が話していることです:
Dog dog = new Dog();
Ball ball = dog.getBall();
または、さらにばかげた例:
Dog dog = new Dog();
dog.setWeight("23kg");
これを現実に想像できますか?毎日書いているような感じですか?「はい」の場合、あなたは手続き型プログラマーです。ただそれを認めてください。David West が著書の 30 ページで次のように述べています。成功した手続き型開発者を成功した客観的開発者に変えるための最初のステップは、ロボトミー手術です。ロボトミー手術が必要ですか? 私にはそれが絶対に必要で、ウェストの『オブジェクト思考』という本を読んでいるときに手に入れました。 客観的思考 オブジェクトのように考え始めると、これらのメソッドの名前がす​​ぐに変更されます。得られるものは次のとおりです。
Dog dog = new Dog();
dog.take(new Ball());
Ball ball = dog.give();
今では私たちは犬を、私たちからボールを​​奪うことができ、私たちが求めれば返してくれる本物の動物として扱います。念のため、犬は NULL を返せないことに注意してください。犬は NULL が何なのかを知りません。客観的思考 (思考) により、コードから NULL 参照がすぐに削除されます。ゲッター/セッター。 悪。 そしてポイント-3
ワンダと呼ばれた魚 (1988) チャールズ・クライトン
さらに、客観的思考は、この例の「犬の体重」などのオブジェクトの不変性につながります。コードを次のように書き換えます。
Dog dog = new Dog("23kg");
int weight = dog.weight();
犬は、体重、大きさ、名前などを外部の人が変えることを許さない不変の生き物です。彼女は、要求に応じて、自分の体重や名前を「伝える」ことができます。オブジェクトの特定の「内部」プロパティに対するクエリを公開するパブリック メソッドには何の問題もありません。ただし、これらのメソッドは「ゲッター」ではないため、「get」プレフィックスを決して受け取るべきではありません。私たちは犬から「抜け出す」ことはできません。彼女の名前は分かりません。私たちは彼女に名前を教えてもらいます。違いがわかりますか? ここではセマンティクスについてさえ話していません。私たちはプログラミングへの手続き型アプローチとオブジェクト指向型アプローチを区別します。手続き型プログラミングでは、データを操作し、取得し、設定し、必要に応じて削除します。私たちが責任を持っており、データは単なる受動的なコンポーネントです。私たちにとって犬は何の関係もありません。単に「データが含まれている」だけです。彼女には自分の人生がありません。そこから必要なものすべてを自由に取得(取得)し、任意のデータをそこに入力(設定)できます。これが、C、COBOL、Pascal、その他の手続き型言語の仕組みです。そして、オブジェクト指向の世界では状況がまったく逆になります。ここでは、オブジェクトを、独自の生年月日と死亡の瞬間、独自の性格や習慣を持つ生き物として扱います。犬にデータ (体重など) を要求すると、犬はその情報を返してくれます。ただし、犬が主体であることを常に忘れないでください。リクエストの後に何が起こるかは彼女が決めます。だからこそ、オブジェクトのメソッドが set または get で始まるのは絶対に間違っています。そして、これは多くの人が考えているように、カプセル化に違反するということでさえありません。これは、オブジェクトのように考えているか、Java 構文を使用して COBOL で記述しているかのどちらかという事実に関係しています。 PS。「JavaBeans、JPA、JAXB、その他 get/set に依存する多くの Java API はどうなるのでしょうか?」と疑問に思うかもしれません。アクセサーの作成を容易にする Ruby の組み込み関数についてはどうでしょうか? まあ、何と言えばいいでしょうか...あなたは運が悪いです。実際のオブジェクトの素晴らしい世界を理解し、受け入れるよりも、手続き型 COBOL の原始的な世界に留まる方がはるかに簡単です。 追伸_ 言い忘れていましたが、セッターを介して依存関係を挿入することもひどいアンチパターンです。しかし、それについては次の投稿で詳しく説明します。 原著
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION