あなたが提起している質問/問題がいくつかあるので、それぞれ個別に扱います。
プライベート メソッドをテストするにはどうすればよいですか?
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 つのクラスを提供しています: PrivateObjectとPrivateType
社内開発プロセスの制限を考慮すると、コア コードを変更することなく、メイン プロジェクト ライブラリの外部で独自のテストを管理できるため、これが最善の策である可能性があります。
Silverlight (およびおそらく他の Core-CLR ランタイム) は、リフレクション中に非パブリック アクセスを厳密に適用するため、このオプションはそのような場合には適用されないことに注意してください。
したがって、プライベート メンバーをテストする方法はいくつかありますが、それを行うためのより賢い/それほど賢くない方法がいくつか潜んでいると確信しています。
すべてのプライベート メソッドに __ プレフィックスを付けるか、プライベートだがアクセス可能なアクセス修飾子を導入することで、これらすべての利点を達成できるでしょうか?
あなたが挙げた(他の人を引用して)利点は次のとおりです。
- 実装をよりクリーンにする/IDE オートコンプリートでメソッドの縦に長いリストを避ける
- どのメソッドがパブリック インターフェイスであり、どのメソッドが変更される可能性があり、実装のみを目的としているかを世界に発表する
- 可読性
これらはすべて __ を使用するか、言語仕様および/またはプライベートだがアクセス可能なアクセス修飾子をサポートする 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 つの側面にすぎませんが、仕様では使用しないことが推奨されています。