1

トロールするつもりはありませんが、本当にわかりません。言語設計者が命名規則 (Python の __ を参照) の代わりにプライベート メソッドを許可するのはなぜですか?
私は答えを探しましたが、通常の引数は次のとおりです。a
実装をよりクリーンにする/IDEオートコンプリートのメソッドの長い縦型リストを避けるため
b)どのメソッドがパブリックインターフェイスであり、変更される可能性があり、実装目的のためだけであるかを世界に発表するため
c )可読性

わかりましたので、すべてのプライベート メソッドに __ プレフィックスを付けて名前を付けるか、IDE (オートコンプリートに入れないでください) や他のプログラマ (本当に必要な場合を除き、使用しないでください)。地獄、これを本当に思いとどまらせるために、プライベートメソッドにアクセスするために unsafe-like キーワードを要求することさえできます。
私はいくつかのC#コードを扱っており、テスト目的でプライベートメソッドをパブリックに変更し続けているため、これを求めています。その間の多くのプライベートメソッド(xmlシリアル化の文字列ジェネレーターなど)はデバッグ目的(文字列の一部の書き込みなど)に非常に役立ちますログファイルなど)。
だから私の質問は:
アクセス制限で実現できても、アクセスを制限しない命名規則では実現できなかったものはありますか?

4

6 に答える 6

10

あなたが提起している質問/問題がいくつかあるので、それぞれ個別に扱います。

プライベート メソッドをテストするにはどうすればよいですか?

private Methods をテストする必要があるかどうかの議論/議論を超えて、これを行う方法がいくつかあります。

リファクタリング
一般的な一般的な答えは、元のクラスが利用する別のテスト可能なクラスに動作をリファクタリングできるということです。これは議論の余地があり、設計や特権によっては常に適用できるとは限りません。

InternalsVisibleTo
一般的なルーチンは、テスト可能なロジックをメソッドに抽出し、それを としてマークすることinternalです。アセンブリ プロパティで、属性を追加できます[InternalsVisibleTo("MyUnitTestingProject")]。これにより、他のすべてのアセンブリへのアクセスを隠しながら、単体テスト プロジェクトからメソッドにアクセスできます。http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

ただし、あなたのコメントを考えると、職場でソース コードの構造を永続的に変更することはできません。アクセサーをテスト、テスト、コミットする前に元に戻すように変更していること。この場合、次の 2 つのオプションがあります。

クラスを部分的にテスト
する クラスをpartial. テスト (またはプライベート メンバーへのパブリック ラッパー) を含む 2 番目の部分クラス ファイルを作成します。次に、マージ/コミットするときが来たら、プロジェクトから部分クラスを削除partialし、メイン クラスからキーワードを削除します。さらに、テスト コード ファイル全体をif DEBUG(または他のディレクティブ) でラップできるため、単体テスト時にのみ使用でき、運用/開発コードには影響しません。 http://weblogs.asp.net/ralfw/archive/2006/04/14/442836.aspx

public partial class MyClass
{
    private string CreateTempString()
    {
        return "Hello World!";
    }
}

#if DEBUG

public partial class MyClass //in file "MyClass_Accessor.cs"
{
    public string CreateTempString_Accessor()
    {
        return CreateTempString();
    }
}

#endif

リフレクション リフレクション
を介して引き続きプライベート メンバーにアクセスできます。}

Test t = new Test();
var publicFieldInfo = typeof(Test).GetField("PrivateField", BindingFlags.Instance | BindingFlags.NonPublic);
Console.WriteLine(publicFieldInfo.GetValue(t)); //outputs "private"

単体テストは、この方法でクラス内の非公開/非表示のデータを引き出すことができます。実際、Microsoft は、まさにこれを行う 2 つのクラスを提供しています: PrivateObjectPrivateType

社内開発プロセスの制限を考慮すると、コア コードを変更することなく、メイン プロジェクト ライブラリの外部で独自のテストを管理できるため、これが最善の策である可能性があります。

Silverlight (およびおそらく他の Core-CLR ランタイム) は、リフレクション中に非パブリック アクセスを厳密に適用するため、このオプションはそのような場合には適用されないことに注意してください。

したがって、プライベート メンバーをテストする方法はいくつかありますが、それを行うためのより賢い/それほど賢くない方法がいくつか潜んでいると確信しています。


すべてのプライベート メソッドに __ プレフィックスを付けるか、プライベートだがアクセス可能なアクセス修飾子を導入することで、これらすべての利点を達成できるでしょうか?

あなたが挙げた(他の人を引用して)利点は次のとおりです。

  1. 実装をよりクリーンにする/IDE オートコンプリートでメソッドの縦に長いリストを避ける
  2. どのメソッドがパブリック インターフェイスであり、どのメソッドが変更される可能性があり、実装のみを目的としているかを世界に発表する
  3. 可読性

これらはすべて __ を使用するか、言語仕様および/またはプライベートだがアクセス可能なアクセス修飾子をサポートする IDE への変更によって達成できることを追加します。言語と IDE の現在の機能/動作を変更することについて議論する価値ないと思います(そして、おそらく StackOverflow には意味がないでしょう) 。

1) よりクリーンな実装と intellisense
Visual Studio IDE (MonoDevelop について話すことはできません) は、[EditorBrowsableAttribute] でマークされている場合、intellisense からのメンバーの非表示をサポートしています。ただし、これは、開発者が Visual Studio オプションで [上級メンバーを非表示] オプションを有効にしている場合にのみ機能します。(同じアセンブリ内で作業している場合、インテリセンスでメンバーを抑制しないことに注意してください) http://msdn.microsoft.com/en-us/library/system.componentmodel.editorbrowsableattribute.aspx

そのため、パブリック メンバーをそのようにマークすると、(インテリセンス的に) 内部っぽい ([InternalsVisibleTo] サポートなし) ように動作します。したがって、同じアセンブリにいる場合、またはHide Advanced Members有効になっていない場合でも、インテリセンスに __ メンバーの長いリストが表示されます。IntelliSense から非表示にしても、現在のアクセス修飾子に従って完全にアクセスできます。

2) パブリック使用インターフェイス/コントラクト
これは、C#、Visual Basic、F#、C++.NET、および任意の .NET 開発の世界のすべての開発者が同じ __ 命名規則を採用し、アセンブリがコンパイルされて交換されるときにそれに準拠することを前提としています。開発者の間。おそらく、IronPython でスクリプトを作成している場合、または会社が社内でこのアプローチを採用している場合は、問題なく使用できます。しかし、一般的に言えば、それは起こらず、.NET 開発者は、一般的な .NET 文化ではないため、この規則を採用するライブラリを活用することを躊躇する可能性があります。

3) 読みやす
さ この種の「読みやすさ」は、文化とその分野の開発者が何を期待しているかに依存するという点で、#2 に当てはまります。それは確かに議論の余地があり、主観的です。私は、C# 開発者の大多数が、コードの可読性を大幅に向上させるために厳密な/強制的なカプセル化を見つけていると確信しています。(余談ですが、開発者がプライベート フィールドに _ または __ プレフィックスを採用し、それらをプライベートに保つことは珍しくありません)

ただし、C# の可読性とカプセル化は、パブリック/プライベート アクセサーだけではありません。C# には、private、public、protected internal、protected、および internal (1 つ足りないのですか?) があり、それぞれに独自の用途があり、開発者にさまざまな情報を提供します。これらのアクセサを __ 経由でのみ通信する方法がわかりません。単一のアンダースコアは保護され、二重のアンダースコアは非公開であることを示唆しているため、読みやすさが確実に妨げられます。


アクセスを制限しない命名規則では達成できなかったもので、アクセス制限によって達成できるものはありますか?

なぜC# の設計チームがこの道をたどったのかという質問がある場合は、いつの日か Hejlsberg 氏に尋ねる必要があると思います。彼らが C/C++ の最良の部分を収集し、オブジェクト指向の原則の原則に重点を置いて言語を作成していたことは知っています。

アクセス修飾子を介してアクセスを強制することによって何が達成されるかについて: API の消費者による適切なアクセスがより保証されます。あなたのクラスMakeTempStringForXMLSerializationがシリアル化のためのクラス プロパティとして文字列を格納するメソッドを利用しているが、パフォーマンス上の理由からコストのかかるチェックを控えている場合 (開発者として、クラスのすべてのフィールドがパブリック API を介して有効であることを確認するために単体テストを行っているため)次に、サードパーティが素敵なガベージインガベージアウトを行います。彼らは、あなたやベンダーの見掛け倒しのライブラリを非難します。それは公平ですか?必ずしも; 彼らはゴミを入れましたが、現実には多くの人が依然としてベンダーを非難しています.

API の仕組みを理解しようとしている新しい開発者にとって、経験を簡素化するのに役立ちます。はい、開発者はドキュメントを読む必要がありますが、パブリック API が直感的であり (一般的にそうあるべきです)、アクセスしてはならない大量のメンバーを公開しない場合、混乱がはるかに少なくなり、誤ってゴミをフィードする可能性が低くなります。システムに。また、開発者が手間をかけずに API を効果的に使用および活用できるようにするためのオーバーヘッドも削減されます。これは特に、内部実装の詳細を変更/リファクタリング/改善したい API の更新を公開する場合に当てはまります。

したがって、ビジネスの観点からは、責任や顧客との悪い関係から彼らを保護し、開発者がそれを購入して投資することをより魅力的にしています.

あなたが言うように、誰もが__メンバーにクラス外でアクセスしてはならないという規則に従うかunsafe、「これを実行して壊れた場合、それは私のせいではありません! " それなら、あなたは C# .NET 開発と同じ地球上にいるわけではありません。C# によって提供されるアクセサーはその__規則を提供しますが、すべての開発者がそれに従うことを保証します。

制限されたアクセスは、コンシューマーがリフレクションを介して回避できるため (上記で説明したように)、錯覚であると主張することができます。したがって、実際には、アクセス修飾子と __ (またはその他の) 表記の間にプログラム上の違いはありません。(Silverlight/Core-CLR では、間違いなくプログラム上の違いがあります!) しかし、これらのプライベート フィールドにアクセスするために開発者が行う作業は、消費者に「入らないでください」というサインで開いたドアを与えることとの違いです。 」 (彼らが読めることを願っています)と、彼らが打ち破らなければならない鍵付きのドア。

結局、それは実際に何を提供するのでしょうか? メンバーへの標準化された、強制されたアクセス。as は、標準化されておらず、強制されていないメンバーへのアクセスを__提供します。さらに、さまざまな利用可能なアクセス修飾子が提供する記述の範囲が不足しています。__

更新 (2013 年 1 月 2 日)

半年が経ちましたが、C# 言語仕様を読んでいて、セクション2.4.2 識別子からこの小さな宝石に出くわしました。

2 つの連続したアンダースコア文字 (U+005F) を含む識別子は、実装で使用するために予約されています。たとえば、実装によって、2 つのアンダースコアで始まる拡張キーワードが提供される場合があります。

必ずしも悪いことは起こらないと思います。ただし、コードで二重アンダースコアを使用することを検討する際に考慮すべきもう 1 つの側面にすぎませんが、仕様では使用しないことが推奨されています。

于 2012-07-05T02:14:47.907 に答える
4

private メソッドが存在する理由は、カプセル化を提供するためです。

これにより、オブジェクトが相互作用するパブリック コントラクトを提供しながら、リファクタリングがコンシューマーに影響を与えないように内部ロジックと状態をカプセル化できます。

たとえば、パブリックの名前付きプロパティを提供しながら、型指定された DataSet と同様に状態をディクショナリに格納することを決定できます。

これは実際には「セキュリティ」機能ではありません (常にリフレクションをオーバーライドする必要があるため) が、パブリック API を内部実装から分離しておく方法です。内部および非公開の実装に「依存」する必要はありません。公開 (または保護された) 実装にのみ依存する必要があります。

さて、単体テストに関しては、通常、内部実装をテストすることは望ましくありません。InternalsVisibleToAttributeただし、一般的なアプローチの 1 つは、Chris が述べたように、内部で宣言し、テスト アセンブリに を介してアクセスできるようにすることです。

また、パブリック、プライベート、およびプロテクトの明確な区別は、オーバーライド可能であると予想されるものとそうでないものを定義する際に、継承で非常に役立ちます。

于 2012-07-05T02:35:34.700 に答える
1

一般に、フィールドまたはメソッドをプライベートとしてマークすることには実際の意味はありません。人工的な安心感を提供します。すべてのコードは同じプロセス内で実行されており、おそらく互いに友好的な関係にある人々によって書かれています。コードを相互に保護するためにアクセス制御が必要なのはなぜですか?それは修正すべき文化的な問題のように聞こえます。

ドキュメントは、プライベート/保護/パブリックよりも多くの情報を提供し、優れたシステムにはとにかくドキュメントがあります。あなたの開発を導くためにそれを使用してください。メソッドを「プライベート」としてマークし、開発者がとにかくそれを呼び出す場合、それは悪い開発者であり、彼は最終的に他の方法でシステムを台無しにします。その開発者を修正します。

アクセス制御は最終的に開発の邪魔になり、コンパイラを満足させるためだけに時間を費やします。

もちろん、厳密にC#について話している場合は、他のC#開発者が期待するため、メソッドをプライベートとしてマークすることに固執する必要があります。

于 2012-07-05T02:20:41.630 に答える
1

特に、実際にそれらの詳細を隠したいライブラリ実装者にとっては、多くの内部詳細が隠されています。

販売されている商用ライブラリがあることに注意してください。彼らは、インターフェースで非常に限られた一連のオプションのみをユーザーに公開し、残りのすべてを適切に隠したいと考えています。

このオプションを提供しない言語を設計する場合は、オープンソース プロジェクト (または主にスクリプト) にほぼ独占的に使用される言語を作成していることになります。私は Python についてあまり知りませんが、Python で書かれた商用のクローズド ソース ライブラリがあるかどうかを知ることは興味深いでしょう。

あなたが挙げた理由も十分です。

于 2012-07-05T02:24:46.100 に答える
1

パブリック メンバーを含むライブラリを公開している場合、ユーザーはこれらのメンバーを使用できます。命名規則を使用して、そうすべきではないことを伝えることができますが、そうする人もいます。

「内部」メンバーが公開されている場合、すべての内部構造を同じに保ち、非常に小さな変更のみを加えない限り、古いバージョンのライブラリとの互換性を保証することは不可能になります。つまり、ライブラリを使用するすべてのプログラムは、コンパイルされたバージョンを使用する必要があります (共有システム バージョンを使用するのではなく、独自のバージョンを出荷することでこれを行う可能性が最も高くなります)。

これは、ライブラリにセキュリティ アップデートがある場合に問題になります。せいぜい、すべてのプログラムが異なる共有バージョンを使用しており、セキュリティ更新プログラムを、出回っているすべてのバージョンにバックポートする必要があります。ほとんどの場合、すべてのプログラムは独自のバージョンを出荷しており、そのプログラムの作成者が更新しない限り、単に更新を取得することはできません。

パブリック API を慎重に設計し、変更する可能性のあるものに対してプライベート メンバーを使用すると、重大な変更を最小限に抑えることができます。その後、すべてのプログラム/ライブラリは、以前のライブラリ用にコンパイルされていても、ライブラリの最新バージョンを使用でき、更新の恩恵を受けることができます。

于 2012-07-05T02:34:34.127 に答える
0

これは、いくつかの興味深い議論につながる可能性があります。プライベートメソッド(およびメンバー変数)をマークする主な理由は、情報の隠蔽を強制することです。外部コードは、クラスがどのように機能するかを認識したり気にしたりするべきではありません。他のものを壊すことなく、自分のimplを自由に変更できるはずです。これは十分に確立されたソフトウェアプラクティスです。

ただし、実際には、プライベートメソッドがテストの邪魔になり、予期しない変更が発生する可能性があります。Pythonは「私たちはすべて大人に同意している」という信念を持っており、プライベートメソッドを推奨していません。そのため、命名規則を使用したり、「一般向けではない」とコメントしたりすることがあります。これは、OO理論と現実の問題のもう1つです。

于 2012-07-05T02:19:46.433 に答える