プロパティのポイントは何ですか?


11

プロパティと私の反論に対するいくつかの議論は次のとおりです。

getterおよびsetterメソッドを書くよりも使いやすい

ゲッターメソッドとセッターメソッドのペアはコードのにおいです。これらの記述を簡単にすることは、Scantronフォームを使用してすべての「C」を入力することにより、数学テストに失敗しやすくするようなものです。永続化のために状態のみを含むオブジェクトは、getter / setterを使用してはならず、永続化時に不変オブジェクトを作成する必要があります。

オブジェクトのコンシューマーにとって重要なのは、オブジェクトが行う方法ではなく、オブジェクトが行うことです。その振る舞いはそれがすることです。その状態は、その方法です。オブジェクトの状態を気にかけている場合(永続性を除き、これもオブジェクト指向を破壊します)、OOPを実行せず、その利点を失います。

彼らは消費者にパフォーマンスの大まかな指標を与えます

これは、特定のプロパティについて、将来変更される可能性があるものです。リリース1.0で、PropertyXにアクセスするとフィールドが返されるだけだとします。リリース1.5では、フィールドがnullの場合、PropertyXはNull Objectパターンを使用して新しいnullオブジェクトを作成します。リリース2.0では、PropertyXのgetterメソッドによってフィールドがさらに検証されています。

プロパティがますます複雑になるにつれて、プロパティを使用することによるパフォーマンスの指標はますます真実になりそうです。

パブリックフィールドよりも優れている

これは本当です。しかし、メソッドもそうです。

これらはメソッドとは根本的に異なるオブジェクトの側面を表し、オブジェクトのすべてのコンシューマーはこれに注意する必要があります

上記のステートメントの両方が正しいと確信していますか?

入力しやすいです

確かに、タイピングmyObject.Lengthはタイピングよりも簡単ですがmyObject.Length()、それを少しの構文糖で修正することはできませんか?


プロパティの代わりにメソッドを使用する理由

  • パフォーマンスの保証はありません。メソッドがより複雑になっても、APIは真実のままです。消費者は、パフォーマンスの問題に直面している場合、コードをプロファイルする必要があり、APIに依存しません。

  • 消費者が考えることは少なくなります。このプロパティにはセッターがありますか?メソッドは確かにそうではありません。

  • 消費者は適切なOOPの考え方から考えています。APIのコンシューマーとして、オブジェクトの動作と対話することに興味があります。APIでプロパティを見ると、状態によく似ています。実際、プロパティの実行が多すぎる場合は、プロパティであってはなりません。したがって、実際には、APIのプロパティはコンシューマに表示される状態です。

  • APIのプログラマは、戻り値を持つメソッドについてより深く考え、可能であれば、そのようなメソッドでオブジェクトの状態を変更することを避けます。可能な限り、コマンドをクエリから分離する必要があります。


それでは、なぜメソッドの代わりにプロパティを使用するのですか?MSDNのほとんどのポイントは、それ自体がコードの匂いであり、プロパティにもメソッドにも属していません。

(CQSについて考えた後、これらの考えが浮かびました。)


5
+1。プロパティは、フィールドの構文を持つメソッドであり、意味がありません。
ネマンジャトリフノヴィッチ

23
@Nemanja Trifunovic:type GetFoo() void SetFoo()1万回書いたなら、それは完全に理にかなっています。C#コードを書いている間ずっと、プロパティに混乱することはありませんでした。
エドS.

23
すでに決心したように思えます。質問はなんですか?
ディーンハーディング

9
@Nemanja Trifunovic:「ゲッターとセッターは一般的に悪い」あなたは何度でもそれを繰り返すことができますが、それは真実になりません。なぜ彼らが悪いと思うのか説明してみてはいかがですか?基になる変数名の代わりにプロパティ名を入力したためにSOがクラッシュする限り、プロパティを呼び出すとすぐにプログラムがクラッシュすることを考えると、エラーを見逃すことは不可能です。それが起こったとき、私はそれを引き起こすために何をしたかを正確に知っており、2秒で修正しました。問題は見当たりません。
エドS.

3
@NemanjaTrifunovicに指摘するだけで、ゲッターメソッドとセッターメソッドが邪悪な記事である理由はかなり古くJavaについてであり、Javaの弱点、つまりプロパティないことの弱点を強調しています。(したがって、実装の詳細が多すぎることを示しています)…ここでテールを噛みます。(
gettersとsetters

回答:


44

なぜ「プロパティに対するメソッド」なのですか?メソッドは何かをします。プロパティは、オブジェクトのメンバーです。これらはまったく異なるものですが、一般的に記述されている2種類のメソッド(ゲッターとセッター)はプロパティに対応しています。一般にプロパティをメソッドと比較することは意味がないので、ゲッター/セッターについて話すつもりだったと思います。

ゲッターメソッドとセッターメソッドのペアはコードのにおいです。

必ずしもそうではない、と私は主張しますが、どちらにしても、これはゲッター/セッター対プロパティの問題ではなく、どちらを使用すべきかという問題です。またsetX、読み取り専用のプロパティを作成できるのと同じように、パーツを除外できることにも注意してください。

オブジェクトのコンシューマーにとって重要なのは、オブジェクトが行う方法ではなく、オブジェクトが行うことです。その振る舞いはそれがすることです。その状態は、その方法です。オブジェクトの状態を気にかけている場合(永続性を除き、これもオブジェクト指向を破壊します)、OOPを実行せず、その利点を失います。

非常に疑わしい態度。GUIがa DataStuffManagerImplに保持されているデータを出力する場合、何らかの方法でその数値を取得する必要があります(そして、アプリケーションの半分をウィジェットクラスに詰め込むことはオプションではありません)。

プロパティがますます複雑になるにつれて、プロパティを使用することによるパフォーマンスの指標はますます真実になりそうです。

[メソッドがあります]パフォーマンスの保証はありません。メソッドがより複雑になっても、APIは真実のままです。消費者は、パフォーマンスの問題に直面している場合、コードをプロファイルする必要があり、APIに依存しません。

ほとんどすべての場合、すべての検証ロジックなどは事実上O(1)であるか、そうでなければコストが無視できます。そうでない場合、おそらくあなたは行き​​過ぎであり、それは変更の時間です。また、getX()メソッドは通常、安価なものとして扱われます!

確かに、myObject.Lengthを入力する方がmyObject.Length()を入力するよりも簡単ですが、それを少し構文的な砂糖で修正することはできませんか?

プロパティその構文糖です。

消費者が考えることは少なくなります。このプロパティにはセッターがありますか?メソッドは確かにそうではありません。

「このゲッターのセッターはありますか?」同じ違い。

APIのプログラマは、戻り値を持つメソッドについてより深く考え、可能であれば、そのようなメソッドでオブジェクトの状態を変更することを避けます。可能な限り、コマンドをクエリから分離する必要があります。

ここで何を伝えようとしているのかわかりません。プロパティについては、副作用を引き起こさない、より強力な未定の法律があります。


3
+1、およびその不文律ではありません。MSDNのプロパティ使用ガイドラインには、他の多くの人と一緒に書かれています。OPは多くの疑問を明確にするために、それらを通過すべきだと思います。また、携帯電話からこれを書いているので、ここにリンクを投稿することはできませんが、ガイドラインは簡単に見つけられるはずです。
デサイクロン


@delnan:プロパティはそのような構文上の糖ではありません。プロパティはフィールドのように扱うことができます(セッターがある場合、それらは割り当てターゲットとして使用できます)。メソッドはできません。
xofz 2011

1
@SamPearson:にobj.x = yマップしobj.setX(y)、にobj.xマップしobj.getX()ます。どう違いますか?

1
@SamPearsonでは、プロパティセッターとゲッターの可視性を互いに独立して変更できます。私はこれをEntity Frameworkオブジェクトで常に使用しています。セッターは保護されています(したがって、フレームワークのみが値を設定できます)。それは許可せずにint型の長さ= myObject.Lengthを言うために完全に実行可能ですのでmyObject.Length = 10
マイケル・ブラウン

19

ゲッターメソッドとセッターメソッドのペアはコードのにおいです。

それは誤った仮定であり、完全に間違っています。Get / Setメソッドは、データメンバーをカプセル化する方法であり、決して「コード臭」ではありません。「コードの匂い」という言葉を周りの人が投げる方法は本当に嫌いですが、とにかく...

これは、特定のプロパティについて、将来変更される可能性があるものです。リリース1.0で、PropertyXにアクセスするとフィールドが返されるだけだとします。リリース1.5では、フィールドがnullの場合、PropertyXはNull Objectパターンを使用して新しいnullオブジェクトを作成します。リリース2.0では、PropertyXのgetterメソッドによってフィールドがさらに検証されています。

プロパティがますます複雑になるにつれて、プロパティを使用することによるパフォーマンスの指標はますます真実になりそうです。

設計が不十分なAPIのように聞こえますが、それがプロパティ構文の欠点であるとは思いません。

C#のプロパティは、プログラマとしての私たちの生活を少し楽にする非常に一般的なパターンの単なる構文上の砂糖でした。ただし、最近では、データバインディングを使用する場合、プロパティを使用する必要があります。そのため、これらは構文上の砂糖よりも少し多くなっています。私は本当にあなたの点のどれにもまったく同意していないと思うし、あなたが共通のパターンを直接サポートする言語機能を嫌う理由を理解していないと思う。


1
コードの匂いよりも良い用語を思い付くために、私は報奨金を与えるつもりです。リファクタリングに関する本を約1,000回使用するだけで読んでください。黒板の爪のようなものです。
-JeffO

1
@ジェフO:ええ、私はその用語を最も一般的に使用しているように見える人々は多くの経験を持っていないことがわかります。
エドS.

6
@Jeff Oと@Ed S:IME、「コードのにおい」は、「好きではないが、実際には理由がない」という意味で人々がよく使う用語になっています
Steven Evers

3
@SnOrfus:はい、または「メソッドがX行を超えてはならない」など、実際にはほとんど意味をなさない「宗教」ビューを保持している場合、通常はどこかで読んだものの単なる繰り返しです。
エドS.

1
getter / setterメソッドの不適切な使用はコードの匂いですが、何も不適切に使用されるべきです。ユースケースが狭い場合でも、そのようなユースケースにそのようなものを使用することは、コードのにおいとは見なされません。すべてのセッターの作成は盲目的な習慣ではありませんが、適切なときにそれらを含めることを恐れてはいけません。必要なのは、クライアントが状態を変更できることと、将来状態が以前に何であったかを知ることができることのバランスをとることです(状態が不変の場合は簡単です)。どちらも便利ですが、コードはどちらかを選択する必要があります。
supercat 14

10

あなたの前提は間違っています。

プロパティは、パフォーマンスや内部実装などとは一切関係ありません。
プロパティは特別なメソッドのペアであり、必要に応じて意味的に属性を表します。したがって、唯一のコントラクトは、属性が動作することを期待するようにプロパティが動作することです。
オブジェクトの色を要求する場合、プレーンフィールドアクセスによって取得されたのか、それとも時間内に計算されたのかを推測しません。
全体のポイントは、メソッドを使用して属性の動作を公開する機能を持つことですが、フィールドまたはアクセサーを使用しているかどうかにかかわらず、インターフェイスのコンシューマーに対して透過的です。

属性を持つこと(およびプロパティがフィールドとは反対であるため、実際に実装を隠すこと)は強力な宣言機能です。これは、データバインディングおよびその他の多くの便利な機能のために、ビジュアルオブジェクトインスペクターおよびその他の自動ビュー生成を行うための基盤です。そして最も重要なことは、この情報を同僚のプログラマーにも明確に伝えることです。


6

消費者は適切なOOPの考え方から考えています。APIのコンシューマーとして、オブジェクトの動作と対話することに興味があります。APIでプロパティを見ると、状態によく似ています。実際、プロパティの実行が多すぎる場合は、プロパティであってはなりません。したがって、実際には、APIのプロパティはコンシューマに表示される状態です。

プロパティは状態であると想定されています。基礎となるセッターやゲッターのコードを追加するために変更した場合は大幅にセットするのに必要な処理や、その後の状態を取得し、本当にそれはもはや財産ません、あなたがすべき方法でそれを置き換えます。これは、コードの開発者としてのあなた次第です。

セッターまたはゲッターにコードを入れすぎる(どれだけが依存するか)のは間違っていますが、可能だからといって、すべての場合にパターンを捨てるわけではありません。


6

不足していることの1つです。これが無知によるものなのか、意図的にこの詳細を見落としているのかはわかりませんが、プロパティはメソッドです。

C#のプロパティ構文を使用すると、コンパイラはプロパティをファーストクラスの構文機能として理解する言語に通知するメタデータを使用して、getterメソッドとsetterメソッドを静かに作成します。それは、実際、あなたが求めている構文糖衣です。CLRで実行できるいくつかの言語は、この詳細を完全に隠していないわけではなく(Boo、メモリが私に役立つなら、いくつかのLisp実装)、ゲッターとセッターを明示的に呼び出すことができます。

プロパティには、変更通知イベント(INotifyPropertyChangedなど)をトリガーしたり、クラスのインスタンスをダーティとしてマークするなどの副作用がある場合があります。これは、実際の価値がある場所ですが、作成にはもう少し手間がかかります(ただし、構文に精通したマクロを持つBooを除きます)。

さて、より広範な問題は、ゲッターメソッドとセッターメソッドが実際に良いことかどうかです。明らかにトレードオフがあります。ミューテーターメソッドがある場合、スレッドの同期の問題に対処する必要があるため、コードは本質的に並列化可能性が低くなります。そして、ミューテーターメソッド(プロパティまたはゲッター/セッターメソッドと呼ばれるかどうか;それらは同等である)を使用してデメテルの法則に違反する危険性があります。

しかし、時にはそれは正しいことです。問題は、何らかのソースからデータを取得し、それを少し変更し、更新されたデータをユーザーに提示し、変更を保存することです。そのイディオムは、プロパティによって十分に役立っています。以下のようアレンホルブの記事は言う、getterとsetterが問題を抱えているという理由だけで、あなたがそれらを使用しないでくださいという意味ではありません。(Parroting abstract Guruspeakは有害と見なされます)。クラス/責任/共同研究者のアプローチに従ったとしても、情報または情報のプレゼンテーションを誰かに公開することになります。ポイントは、絡み合いの表面積を最小化することです。

プロパティの利点は、別のオブジェクトにそれらを利用させることが非常に簡単であることです。プロパティの欠点は、別のオブジェクトにそれらを利用させることは非常に簡単であり、それを簡単に防ぐことはできないということです。

オブジェクトの突然変異は、たとえばMVCアーキテクチャのコントローラー層で意味があります。それがあなたのコラボレーターです。ビューも共同作業者ですが、責任が異なるため、オブジェクトを直接変更しないでください。プレゼンテーションコードをビジネスオブジェクトに組み込むことは、必ずしもゲッター/セッターを回避する正しい方法ではありません。

純粋なオブジェクト指向ではなく、機能的な抽象化を使用すると、方程式は少し変わります。これにより、一般的に「レコード」オブジェクトのコピーを作成します。そして、パフォーマンスの保証を得ようとしている場合、一般的にプロパティは不変コレクションの遅延再構築よりも予測可能です。


5

私の本でプロパティを使用するもう1つの重要な理由は、プロパティが読みやすさを大幅に向上できることです。

account.setBalance(Account.getBalance()+deposit);

より明らかに読みにくい

account.Balance += deposit;

6
バランスは、それを変更することに関連する重要なビジネスロジックがあることが確実であるため、プロパティであってはならないことを除きます(当座貸越のチェック、サービス料の請求、トランザクションの記録など)。温度、背景色など)
ケイトグレゴリー

9
account.Deposit(amount)を選択しないのはなぜですか?
xofz

4
@サムピアソン:+1。ゲッター/セッターがデザインの悪さを示す理由の完璧な例です。
ネマンジャトリフノヴィッチ

4

あなたは私に対してほとんど反対の宗教的視点を持っています:)

DelphiからJavaに移行したとき、プロパティの不足は私にとって大きなa辱でした。私は、プロパティを宣言し、プライベート変数を直接指すか、(保護された)ゲッターとセッターを記述して、それらをプロパティに「配管」することに慣れていました。これにより、プロパティがカプセル化され、明確で明確な方法でアクセスする方法が制御されました。アクセス時に合計を計算する読み取り専用プロパティを用意し、「_ getTotal()」または同様のバロックではなく「Total」と呼ぶことができます。また、抽象基本クラスでプロパティを保護してから、サブクラスでパブリックまたは公開に移動することで、プロパティへのアクセスを制限できることも意味していました。

私にとって、プロパティはオブジェクトの状態を設定および取得する、より自然で表現力のある方法です。強制されていないコーディング規則に依存することは、プロパティを批判しているものよりも「コード臭」です。また、他の人が言ったように、不適切に設計されたプロパティの使用を考え出し、その失敗を使用して一般的にプロパティの概念を試して捨てることは非常に悪い形です。プロパティの不適切な使用のみを見たことがある可能性がありますが、それが私が思う方法であると仮定しますが、独断的になりすぎる前にもっと研究する必要があります。


+1それは実際、プロパティの実際の使用です。素晴らしい答え。「また、抽象基本クラスでプロパティを保護し、サブクラスでパブリックまたは公開に移動することで、プロパティへのアクセスを制限できることを意味しました。
Karthik Sreenivasan

Delphiは、プロパティと悪心を悪用します。リストをソートせず、そのsorted プロパティをに設定しますtrue。このように設定するとfalse、元のリストが得られます。:Dそれともランダムにシャッフルしますか?:Dまたは何でも、それはただ愚かです。さらに、適切に並べ替えられたセットと比較して非常に遅いです。プロパティは悪くありませんが、非常に控えめに使用することを学びました(ゲッターとセッターに非常に満足するまで、ほとんどJavaを使用しています)。
-maaartinus

1

Java Beansフレームワークにプロパティが導入された理由の1つは、IDEとの統合を可能にするためです。これらのコンポーネントをIDEにドラッグし、プロパティエディタを使用してプロパティを編集できます。

(当時は通常のゲッターとセッターだけでした-そして命名規則によってのみ定義されていました-そしてこれは実際に匂いがしました)

今日では、デバッグ中など、通常のコードを使用せずにプロパティにアクセスして変更するケースがさらに増えています。


1

もう1つの角度-彼らは本当にVBから来ました。.NETが考え出された20世紀の暗い時代に戻って、VBの簡単なドロップイン置換であるため、VBプログラマーはWebフォームにドラッグアンドドロップできるだけでした。VBにはプロパティがあったため、適切に翻訳するにはその機能を維持する必要がありました。


1
Anders HeljsbergはC#(および一部のIL)を設計し、Delphiも設計しました-これにはプロパティがありました。
ジェシーC.スライサー

1

プロパティには少なくとも2つの目的があります。

  • 彼らは概念的に、彼らがしている場合でも、フィールドと同一の実装は異なります。ゲッターはオブジェクトの状態を変更してはならず、副作用もありません。セッターは、フィールドの変更と概念的に同様の方法で状態を変更するだけで、他の副作用はありません。

  • これらは、パブリック(おそらく読み取り専用)フィールドと構文的に同じです。これは、ソースレベルで呼び出し元を中断することなく、パブリックフィールドをプロパティに変更できることを意味します。


はい、ただし「should」という言葉に注意してください。ゲッターが副作用を起こすことを防ぐプロパティについては何もありません。実際、私はそれが当てはまるケースを数多く見てきました。
ネマンジャトリフノヴィッチ

1
パブリックフィールドをプロパティに変更すると、バイナリ互換性壊れます。消費コードは再コンパイルする必要があります-変​​更されていませんが、私が推測しているのはあなたが得ていたものです:)
MattDavey

@MattDavey:ありがとう。それが私が意味したことです。編集済み。
-dsimcha
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.