2

実装とインターフェイスの区別の価値は理解していますが、ほとんどの OO システムがプライベート メンバーへのアクセスでエラーを出す理由がわかりません。

私は確かに、メイン プログラムでプライベート メンバーにアクセスしたくありません。
しかし、テストとデバッグのためにアクセスしたいと思います。

警告ではなくエラーを発行する正当な理由はありますか? 私の見方では、テストできるコードを書くことを余儀なくされていますが、それはインターフェースの言語サポートを利用していないか、言語サポートを使用していてもテストが困難です。

編集

パブリック インターフェイスの使用を提案した人向け。できますが、あまり説得力がありません。
概念的なレベルでは、誰がいつのことであるかを気にしないプライバシーは非常に粗雑だと思います。
フレンド クラスは合理的な解決策のように思えます。もう 1 つは、「すべて公開」のコンパイラ スイッチである可能性があります。

4

5 に答える 5

1

私の見方では、テストできるコードを書くことを余儀なくされていますが、それはインターフェイスの言語サポートを利用していないか、言語サポートを使用していますがテストが困難です。

private変数や関数にアクセスする必要があるのはなぜですか? それらは、ある時点で関数によって (間接的ではあるが) 呼び出されるか、public呼び出す方法がないため、まったく存在しないはずのアクセスできないコードの一部です。考えてみてください。クラスの外部からメソッドを呼び出すことがまったくprivate不可能な場合、そのメソッドは実行されるのでしょうか?

とにかくメソッドを本当にテストしたい場合はprivate、それを独自のクラスにプルできます。さらに、非常に複雑で個別にテストする必要がある場合は、そもそもチャンスを得るに値する可能性があります。もう1つのオプションは、テストする必要がある/テストしたいときにいつでも公開することですが、実際には「実際の」コードを変更しないでください(そのままにしておきますprivate)。他の人が言ったように、一部の言語には、C++ の friend 、 C#の internal 、Java の package-private など、これらのメソッドをもう少し公開することでこれらのメソッドをテストするのに役立つ機能もあります。時折、IDE 自体が支援することさえあります。

警告ではなくエラーを発行する正当な理由はありますか?

大きな理由の 1 つは、あなたが電話をかけられないからではなく、他の人が電話をかけられないからです。これを想像してみてください。かなりの数のクライアントが使用するライブラリを作成しています。呼び出す必要のないものはすべてマークしてあり、private必要な機能はすべて公開されています。プログラマーは先に進んであなたのライブラリーを使い始め、それを使って大量のコードを書き、自分自身と自分のクライアントの両方から満足のいく顧客を生み出します。

数か月後、大成功を収めたライブラリにスパイスを加えることに決め、少しリファクタリングを行う必要があることに気付きました。したがって、いくつかのメソッドを [名前変更、パラメーターの追加/削除、削除] しますprivateが、シームレスなプロセスをアップグレードするために、すべてのパブリック メソッドのインターフェイスをまったく同じに保つように注意してください。しかし、この世界では、変数にアクセスしたときにコンパイラは警告のみを発行し、エラーは発行しませんprivate。クライアント プログラマの何人かは、それらのprivateメソッドを呼び出すコードを作成しました。さて、ライブラリの新しいバージョンにアップグレードしようとすると、それらを呼び出すことができないため、実際のエラーが多数発生します。privateメソッドはもうありません。今、彼らはコードの何が問題だったのかを見つけるのに時間を費やし、何も覚えていない潜在的に大きな部分を書き直さなければなりません (これは 2 年後のことだと言いましたか?)。そのため、ライブラリの使用方法を完全に再学習し、クライアント コードを書き直す必要があり、これは誰にとっても楽しいことではありません。今、彼らは、アップグレードによって文字通りすべてのコードを破壊し、彼らの生活をより困難にするほど思いやりがないことをかなり不満に思っています.

彼らがコードを修正しているときに、彼らは調査して新しいprivateメソッドを呼び出したので、アップグレードを発行するときにインターフェイスを変更することにした場合、サイクル全体が最初からやり直されると思います. あなたにとって少し便利だったのは、あなたにたくさんの不幸な顧客をもたらしただけです.

ちょっと待って、彼らは私のプライベート メソッドを呼び出す馬鹿じゃないの? なぜ彼らは警告を見なかったのですか?これは私のせいではなく、彼らのせいです!

ええ、そうです、それは彼らのせいであり、それらの警告に注意を払うことで問題を防ぐことができたはずです. しかし、すべての人がコード品質の狂信者で、警告を修正して理解したいと思っているわけではなく、かなりの数の人々が警告を無視しています。private問題は、コンパイラが警告ではなく変数やメソッドにアクセスしようとしてエラーを発行した場合、すべてを自分で防止できた可能性があるということです。そうしないと、privateキーワードがまったく存在しない可能性があるためです。これらのメソッドはテストが難しいため、少し時間を失ったかもしれませんが、知性の低い人がコードを悪用したり、後で問題が発生した場合にあなたを責めたりすることを防ぐ力を得ることができます.

ソフトウェア開発 (および一般的な製品設計) の私のお気に入りの信条の 1 つは、物事は正しく使用するのは簡単で、間違って使用するのは困難または不可能であるべきだということです。真のプライベート メンバーは、文字通りコードを正しく使用できなくするため、このアドバイスの具現化です。

[仮定のレトルト:] まあ、私のコードを使っている人たちは、それを理解するのに十分賢いはずです。私が彼らに求めているのは、コードを正しく使用するために少し余分な時間を費やすことだけです.

コードの品質を向上させ、使いやすくするために必要な時間を費やすことを意識的に拒否していますか? 次に、あなたのコードとは何の関係もありません。明らかに、クライアントの時間よりもあなたの時間が重要です。そのため、プロジェクトの Web ページを閉じて、次の Google 検索結果をクリックするのに必要な 2.5 秒かかります。あなたが使用しているライブラリには、あなたが思っているよりもはるかに多くのprivateメンバーがいます。素晴らしいことは、あなたがそれらについて心配するのに 1 ミリ秒も費やす必要がないということです。で提供されている、より簡単で優れた方法からpublicインターフェース。すべてがパブリックまたは弱い警告を発行するプライベートである場合、実際に必要なものを見つける前に、より多くの関数をふるいにかける必要があります。

メンバー関数の前に入力するときはいつでもprivate、自分以外は誰もそれに触れることができないため、将来の任意の時点で好きなように変更する権限を自分自身に与えたことになります。他の誰かがそれにアクセスしようとすると、ショー停止エラーが発生します。これは、コンパイラーがあなたの背中を持っており、必要なものすべてをより使いやすい形式で完全に提供している場合、コードで愚かなことをさせないためです。あなたのpublicインターフェースで。

はい、現時点ではテストが少し難しくなりますが、将来リファクタリングしてコードを他の人が使いやすくするときに心配する必要がないことも保証されています. 先に進んで、一時的に公開してください (私はあなたの「すべて公開のコンパイラ スイッチのアイデアが好きです :)」が、完了したら元に戻すことを忘れないでください。より適応性の高いコード。:D

于 2012-06-24T01:03:39.183 に答える
0

明らかな理由は、あまりにも多くの人が多くの (すべて?) 警告を無視しているように見えるからです。一部の言語 (Python など) では、あなたが言ったとおりです。「プライベート」であることは、基本的に、それを直接使用する外部コードに対するアドバイスですが、コンパイラはそれを強制しません。

それがどれほど理にかなっているのかについては、言語によって異なると思います.C++のようなものでは、それらに対する態度(「マキャベリではなくマーフィーから保護する」)は、エラーではなく警告であることの正当化と見なすことができます。

Ada では、控えめに言っても、それははるかに冷静な歓迎を受けるだろうと言っても過言ではありません (だからといって、C++ プログラマーからも好意的に受け止められるとは思いませんが、彼らはその考えをまったく嫌わないかもしれません)。ほとんどの Ada プログラマーと同じです)。

一方で、外部インターフェイスを介して (少なくとも十分に) テストできないクラスの設計について疑問に思う必要があります。まれに(とにかくまれであるべきですが)、テストクラスを友達にすることは正当化するのがかなり簡単だと思います(C++の用語では、他の多くは同様の概念を持っていますが)。

于 2012-06-24T00:35:23.113 に答える
0

完全なカプセル化にはいくつかの利点があります。

  • セキュリティ。強力なカプセル化を備えた厳密に型指定された OOP 言語は、プログラム内のデータのセキュリティについて一定の保証を持つことができます。Java 言語は安全性とセキュリティを考慮して設計されているため、特定のライブラリ クラス (Stringや などSecurityManager) のフィールドにアクセスすることはできません。これにより、悪意のあるコードがこれらのオブジェクトに対して悪いことを行うのを防ぎ、コードがオブジェクトが安全であると想定できるようになります。

  • 保守性privateフィールドとメソッドを保持する主な理由の 1 つはprivate、実装をシームレスに変更できるようにすることです。パブリック インターフェイスが更新されない限り、更新されたクラスを使用するコードは変更なしで機能します。フィールドへのアクセスを許可してからprivate実装を変更すると、無限の量のコードが壊れる危険があります。

  • 安定性/検証可能性/テスト可能性。通常、クラスはそのフィールドに不変条件を課します。たとえば、動的配列の実装では、実際に使用されているスペースの量を追跡するフィールドが要素の総数に対応している必要があります。private警告があってもフィールドに自由にアクセスできるようにすることで、これらの不変条件を破ることができます。不変条件を当てにする能力がなければ、コードの正しさについて推論することは困難または不可能になります。さらに、コードのどこかで不変条件を破る場合は、オブジェクトにアクセスできるプログラム内のすべてのコードを調べる必要があると考えられます。private分野。強力なカプセル化により、これらの不変条件は破られず、friends またはパッケージ プライベート メカニズムによるセミカプセル化により、参照するコードの量が制限されます。

テストに関する質問については、多くの言語でカプセル化を特定のケースで破ることができます。C++ にはfriend、Java には package-private などがあるので、クラスは「通常はこれらに触れることはできませんが、例外を作成することはできます」と言うことができます。その後、テスト コードをfriendメイン クラスと同じパッケージまたはパッケージ内に作成して、より徹底的にテストすることができます。

お役に立てれば!

于 2012-06-24T00:35:26.590 に答える
0

オブジェクトのインターフェイスでそれを行う方法がない限り、オブジェクト内の何かにアクセスすることを忘れる必要があると私は考えています。実装固有のプライベートメンバーに直接アクセスしようとしている場合、正しい OO システムはエラー (警告ではなく) を発行する必要があると思います。私は最近、このテーマに関する Kevlin Heney による優れた講演に参加しましたが、非常に役立つことがわかりました。 in-Java (主に Java に関するものですが、他のオブジェクト指向システムとの比較も含まれていることに注意してください)

テストでは、ほとんどの場合、テスト対象のコードのほとんどがパブリック インターフェイス呼び出しでカバーされていることがわかります。完全に 100% のカバレッジを得るためにランタイム リフレクションのようなものを使用する必要があるのは、ごくまれなケースです。

于 2012-06-24T00:43:33.963 に答える
0

「カプセル化を強力に実施することで、上司がプライベート メンバーを踏みにじるのを防ぐことができます」と投稿しようとしていました。 それが間違っているように聞こえるかもしれないことに気付くまでは、しかしよく考えてみると、おそらくほぼ正しいでしょう。

于 2012-06-24T00:57:29.830 に答える