保護されたメンバー/フィールドは本当に悪いですか?
-
02-10-2019 - |
質問
ここで、C#のMSDNの命名規則を読むと、公共および保護されたフィールドよりもプロパティが常に好ましいと述べていることがわかります。一部の人々から、公共または保護されたフィールドを使用してはいけないと言われています。今、私はまだ公共の場を持っている必要があるが、保護された分野が本当に悪い理由をまだ見つけていないことに同意します。
価値を取得/設定するときに特定の検証チェックが実行されることを確認する必要がある場合、私はそれを見ることができますが、私の意見では多くの時間は余分なオーバーヘッドのように思えます。つまり、Basename、PrefixName、およびsuffixName用のフィールドを備えたクラスGameItemがあるとします。プロパティを作成する両方のオーバーヘッドを取る必要があるのはなぜですか(C#
)またはアクセサのメソッドとパフォーマンスヒットが発生します(アプリケーション内のすべてのフィールドに対してこれを行うと、特に特定の言語では少し少なくなると確信しています PHP
または、パフォーマンスを備えた特定のアプリケーションはゲームのように重要です)?
解決
保護されたメンバー/フィールドは本当に悪いですか?
いいえ。彼らはやる気があります。
メンバーがよりアクセスしやすいとすぐに private
, 、あなたはそのメンバーがどのように振る舞うかについて他のクラスに保証をしています。フィールドは完全に制御されていないため、「野生に出て」と言うことで、クラスとクラスを継承したり、より高いバグリスクに相互作用したりするクラスが開きます。フィールドがいつ変更されるかを知る方法はなく、誰または何が変更されるかを制御する方法はありません。
現在、または将来のある時点で、コードのいずれかがフィールドに依存している場合は、特定の値をある程度依存します。これは、期待値がない場合に有効性チェックとフォールバックロジックを追加する必要があります。代わりに、それを気にした財産にすることができたとき、それは膨大な量の無駄な努力です;)
一番 派生クラスと情報を共有する方法は次のとおりです 読み取り専用プロパティ:
protected object MyProperty { get; }
あなたが絶対に 持ってる 読み取り/書き込みにするには、しないでください。あなたが本当に、本当にそれを読み書きしなければならないなら、あなたのデザインを再考してください。それでも読み取りに必要な場合は、同僚に謝罪し、もう一度やらないでください:)
多くの開発者は、これが過度に厳格であると信じており、あなたに言うでしょう。そして、あなたができることは本当です 手に入れてください この厳格でなくても大丈夫です。しかし、このアプローチをとることは、あなたがちょうど堅牢なソフトウェアを手に入れることから行くのに役立ちます。バグの修正に費やす時間がはるかに少なくなります。
パフォーマンスに関する懸念については、しないでください。私はあなたがあなたのキャリア全体で、ボトルネックがコールスタック自体であるほど速くコードを書くことは決してないことを保証します。
他のヒント
わかりました、時間を下げてください。
まず第一に、プロパティはパフォーマンスを傷つけることはありません(あまりしない限り)。それは他の誰もが言うことであり、私は同意します。
もう1つの点は、ブレークポイントを配置してイベントの取得/設定をキャプチャし、どこから来たのかを調べることができるという点で、プロパティが良好であるということです。
残りの議論はこのように私を悩ませます:
彼らは「名声による議論」のように聞こえます。 MSDNがそれを言っている場合、または誰もが好きな有名な開発者や著者が言う場合、それは しなければならない そうしてください。
それらは、データ構造には多くの一貫性のない状態があるという考えに基づいており、さまようか、それらの状態に配置されていることから保護する必要があります。 (私には思われる)データ構造は現在の教育でははるかに強調されているので、通常は 行う それらの保護が必要です。はるかに好ましいことです データ構造を最小限に抑えます そのため、それは正規化され、一貫性のない状態を持たない傾向があります。次に、クラスのメンバーが変更された場合、破損するのではなく、単に変更されます。結局のところ、どういうわけか、多くの優れたソフトウェアがCで書かれていましたが、それは保護の欠如に大きく苦しんでいませんでした。
それらは、極端に運ばれる防御的なコーディングに基づいています。それは、あなたのクラスがあなたのものをグースしないと信頼できない世界であなたのクラスが使用されるという考えに基づいています。これが真実である状況があると確信していますが 私は それらを見たことがありません。何 持ってる 見られるのは、不要な保護を回避するために物事が恐ろしく複雑になった状況であり、恐ろしく過剰に複雑で正規のないデータ構造の一貫性を守ろうとすることです。
フィールドとプロパティに関しては、パブリックインターフェイスでプロパティを好む2つの理由を考えることができます(保護されていることは、クラスだけがそれを見ることができるという意味でも公開されます)。
プロパティを公開すると、実装を非表示にすることができます。また、コードを使用するコードを変更せずに実装を変更することもできます(たとえば、クラスにデータの保存方法を変更する場合)
リフレクションを使用してクラスで動作する多くのツールは、プロパティのみに焦点を当てています(たとえば、シリアル化のライブラリの一部はこの方法で機能すると思います)。プロパティを使用すると、一貫してこれらの標準.NETツールを使いやすくなります。
オーバーヘッドについて:
Getter/Setterがフィールドの値を単純に読み取る/設定する通常の1行のコードである場合、JITはコールにインラインできるようにする必要があるため、パフォーマンスオーバーハッドはありません。
構文的なオーバーヘッドは、自動化されたプロパティ(C#3.0以降)を使用している場合に大幅に減少しているため、これは問題ではないと思います。
protected int SomeProperty { get; set; }
実際、これにより、たとえば作ることができます
set
保護されていますget
非常に簡単に公開されるため、フィールドを使用するよりもさらにエレガントになる可能性があります。
公共および/または保護されたフィールドは、検証なしで宣言クラスの外部から操作できるため、悪いものです。したがって、オブジェクト指向プログラミングのカプセル化原理を破ると言えます。
カプセル化を失うと、宣言するクラスの契約を失います。クラスが意図したとおりまたは期待どおりに動作することを保証することはできません。
プロパティまたはメソッドを使用してフィールドにアクセスすることで、カプセル化を維持し、宣言クラスの契約を履行できます。
読み取り専用のプロパティの回答に同意します。しかし、ここで悪魔の擁護者を演じるために、それは本当にあなたがしていることに依存します。私はいつもパブリックメンバーとコードを書いていることを喜んで認めます(私もコメントせず、ガイドライン、またはいずれかの手続きに従っていません)。
しかし、私が仕事をしているとき、それは別の話です。
実際には、クラスがデータクラスか動作クラスかによって異なります。
もし、あんたが 動作とデータを分離してください, 、動作がない限り、データクラスのデータを公開することは問題ありません。
クラスが動作クラスの場合、データを公開しないでください。