具体的には、インターフェイスと実装者のペアを作成するときに、組織的な問題 (たとえば、s# アーキテクチャで推奨されているように、インターフェイスを別のアセンブリに配置する必要があるなど) が優先されない場合に、それらを構成する既定の方法はありますか?名前空間/命名スキーム?
これは明らかにより意見に基づく質問ですが、これについてもっと考えた人もいると思います。私たちは皆、彼らの結論から恩恵を受けることができます.
具体的には、インターフェイスと実装者のペアを作成するときに、組織的な問題 (たとえば、s# アーキテクチャで推奨されているように、インターフェイスを別のアセンブリに配置する必要があるなど) が優先されない場合に、それらを構成する既定の方法はありますか?名前空間/命名スキーム?
これは明らかにより意見に基づく質問ですが、これについてもっと考えた人もいると思います。私たちは皆、彼らの結論から恩恵を受けることができます.
答えはあなたの意図次第です。
他にもオプションがあると思いますが、ほとんどの名前空間の問題と同様に、プロジェクトのユースケース、およびそれに含まれるクラスとインターフェースに帰着します。
私は通常、インターフェイスを具象型と同じ名前空間に保持します。
しかし、それは私の意見であり、名前空間のレイアウトは非常に主観的です。
Animals
|
| - IAnimal
| - Dog
| - Cat
Plants
|
| - IPlant
| - Cactus
メインの名前空間から 1 つまたは 2 つの型を移動しても、実際には何も得られませんが、using ステートメントを 1 つ追加する必要があります。
私が一般的に行っていることは、階層の上位レベルに Interfaces 名前空間を作成し、そこにすべてのインターフェイスを配置することです (1 つのインターフェイスのみを含む多くの名前空間になってしまうため、そこに他の名前空間をネストする必要はありません)。
Interfaces
|--IAnimal
|--IVegetable
|--IMineral
MineralImplementor
Organisms
|--AnimalImplementor
|--VegetableImplementor
これは私が過去に行った方法であり、多くの問題はありませんでしたが、私のプロジェクトに座っている他の人を混乱させる可能性があることは確かです. 他の人が何をしているのか非常に興味があります。
インターフェイスと実装クラスを同じ名前空間に保持することを好みます。可能であれば、実装クラスに内部可視性を与え、ファクトリを提供します (通常は、ワーカー クラスに委譲する静的ファクトリ メソッドの形式で、フレンド アセンブリ内の単体テストを別のワーカーに置き換えることを可能にする内部メソッドを使用します)。スタブを生成します)。もちろん、具象クラスを public にする必要がある場合 (たとえば、それが抽象基本クラスの場合) は問題ありません。ABC を独自の名前空間に配置する理由がわかりません。
余談ですが、インターフェイス名の前に「I」という文字を付ける .NET の規則は、私は非常に嫌いです。(I)Foo インターフェイスがモデル化するのはifooではなく、単にfooです。では、なぜ Foo と呼べないのでしょうか。次に、実装クラスに具体的な名前を付けます。たとえば、AbstractFoo、MemoryOptimizedFoo、SimpleFoo、StubFoo などです。
(.Net) インターフェイスを別の「共通」アセンブリに保持する傾向があるため、そのインターフェイスを複数のアプリケーションで使用できます。また、多くの場合、アプリのサーバー コンポーネントで使用できます。
名前空間に関しては、BusinessCommon.Interfaces に保持しています。
これは、私も私の開発者も、実装を直接参照する誘惑に駆られないようにするためです。
インターフェイスのみを簡単にデプロイできるように、何らかの方法 (Eclipse のプロジェクトなど) でインターフェイスを分離します。これにより、実装を提供せずに外部 API を提供できます。これにより、依存プロジェクトを最小限の外部でビルドできます。明らかに、これはより大きなプロジェクトに適用されますが、コンセプトはすべての場合に適しています.
私は他の答えに反する私自身の経験を与えます。
私はすべてのインターフェースをそれらが属するパッケージに入れる傾向があります。これにより、パッケージを別のプロジェクトに移動した場合、パッケージを変更せずに実行するために必要なものがすべて揃っていることが保証されます。
私にとって、クラスの機能の一部であるヘルパー関数と演算子関数は、その名前空間のパブリック API の一部を形成するため、クラスと同じ名前空間に入る必要があります。
異なるパッケージで同じインターフェースを共有する共通の実装がある場合は、おそらくプロジェクトをリファクタリングする必要があります。
プロジェクトには、インターフェースではなく抽象的な実装に変換できるインターフェースがたくさんあることが時々あります。
したがって、本当に型または構造をモデル化しているのか自問してください。
私は通常、それらを 2 つの別個のアセンブリに分けます。インターフェイスの通常の理由の 1 つは、一連のオブジェクトをソフトウェアのサブシステムから同じように見せるためです。たとえば、すべてのレポートに IReport インターフェイスを実装しています。IReport は、印刷だけでなく、各レポートの個々のオプションのプレビューと選択にも使用されます。最後に、ユーザーが印刷するレポート (および構成オプション) を選択するダイアログで使用する IReport のコレクションがあります。
レポートは別のアセンブリに存在し、IReport、プレビュー エンジン、印刷エンジン、レポート選択は、それぞれのコア アセンブリおよび/または UI アセンブリに存在します。
ファクトリ クラスを使用して、レポート アセンブリで使用可能なレポートのリストを返す場合、新しいレポートでソフトウェアを更新することは、元のレポート アセンブリに新しいレポート アセンブリをコピーするだけです。Reflection API を使用して、レポート ファクトリのアセンブリのリストをスキャンし、その方法でレポートのリストを作成することもできます。
この手法はファイルにも適用できます。私自身のソフトウェアは金属切断機を実行するので、このアイデアをソフトウェアと一緒に販売する形状とフィッティングのライブラリに使用しています。
ここでも、コア インターフェイスを実装するクラスは別のアセンブリに存在する必要があるため、残りのソフトウェアとは別にそれを更新できます。
同じ名前空間/アセンブリでインターフェイスと実装を見つけると嫌いです。プロジェクトが進化した場合、リファクタリングするのは面倒です。
インターフェイスを参照するときは、すべての実装を取得するのではなく、実装したいと考えています。
私が許容できるのは、インターフェイスをその依存クラスに配置することです(インターフェイスを参照するクラス)。
編集:@ジョシュ、私は私の最後の文を読んだだけです、それは紛らわしいです!もちろん、依存関係クラスとそれを実装するクラスの両方がインターフェイスを参照します。自分自身を明確にするために、例を挙げます:
許容できる :
インターフェイス + 実装:
namespace A;
Interface IMyInterface
{
void MyMethod();
}
namespace A;
Interface MyDependentClass
{
private IMyInterface inject;
public MyDependentClass(IMyInterface inject)
{
this.inject = inject;
}
public void DoJob()
{
//Bla bla
inject.MyMethod();
}
}
実装クラス:
namespace B;
Interface MyImplementing : IMyInterface
{
public void MyMethod()
{
Console.WriteLine("hello world");
}
}
受け付けできません:
namespace A;
Interface IMyInterface
{
void MyMethod();
}
namespace A;
Interface MyImplementing : IMyInterface
{
public void MyMethod()
{
Console.WriteLine("hello world");
}
}
また、インターフェース用のプロジェクト/ガベージを作成しないでください! 例: ShittyProject.Interfaces. あなたは要点を逃しました!
インターフェイス用に予約された DLL (200 MB) を作成したとします。2 行のコードを含む 1 つのインターフェイスを追加する必要がある場合、ユーザーは 2 つの愚かな署名のために 200 MB を更新する必要があります。