web-dev-qa-db-ja.com

クラスとインターフェースのファイルを整理するのに最適な方法は?

OK ..すべての議論の後で、私が扱っている具体的な例をよりよく反映するために、質問を少し変更しています。


私は2つのクラスModelOneModelTwoを持っています。これらのクラスは同様のタイプの機能を実行しますが、互いに無関係です。ただし、CommonFuncModelOneの両方に実装され、ModelTwoに従って除外されたいくつかのパブリック機能を含む3番目のクラスDRYがあります。 2つのモデルはModelMainクラス内でインスタンス化されます(それ自体はより高いレベルでインスタンス化されますが、このレベルで停止しています)。

私が使用しているIoCコンテナーは Microsoft Unity です。私はそれの専門家であるふりをしませんが、私はそれの理解は、インターフェースとクラスのタプルをコンテナーに登録し、具体的なクラスが必要な場合、特定のインターフェースに一致するオブジェクトをIoCコンテナーに要求することです。これは、Unityからインスタンス化するすべてのオブジェクトに対して、一致するインターフェイスが必要であることを意味します。私のクラスのそれぞれが異なる(重複しない)機能を実行するため、これはインターフェイスとクラスの間に1:1の比率があることを意味します1。しかし、それは私が書くすべてのクラスのインターフェースを怠惰に書いているという意味ではありません。

したがって、コード的には2

public interface ICommonFunc 
{ 
}

public interface IModelOne 
{ 
   ICommonFunc Common { get; } 
   .. 
}

public interface IModelTwo
{ 
   ICommonFunc Common { get; } 
   .. 
}

public interface IModelMain 
{ 
  IModelOne One { get; } 
  IModelTwo Two { get; } 
  ..
}

public class CommonFunc : ICommonFunc { .. }

public class ModelOne : IModelOne { .. }

public class ModelTwo : IModelTwo { .. }

public class ModelMain : IModelMain { .. }

問題は、私のソリューションをどのように整理するかです。クラスとインターフェースを一緒にしておくべきですか?または、クラスとインターフェイスを一緒にしておくべきですか?例えば:

オプション1-クラス名で整理

MySolution
  |
  |-MyProject
  |   |
      |-Models
      |   |
          |-Common
          |   |
          |   |-CommonFunc.cs
          |   |-ICommonFunc.cs
          |
          |-Main
          |   |
          |   |-IModelMain.cs
          |   |-ModelMain.cs
          |
          |-One
          |   |
          |   |-IModelOne.cs
          |   |-ModelOne.cs
          |
          |-Two
              |
              |-IModelTwo.cs
              |-ModelTwo.cs
              |

オプション2-機能別に整理されています(ほとんど)

MySolution
  |
  |-MyProject
  |   |
      |-Models
      |   |
          |-Common
          |   |
          |   |-CommonFunc.cs
          |   |-ICommonFunc.cs
          |
          |-IModelMain.cs
          |-IModelOne.cs
          |-IModelTwo.cs
          |-ModelMain.cs
          |-ModelOne.cs
          |-ModelTwo.cs
          |

オプション3-インターフェースと実装の分離

MySolution
  |
  |-MyProject
      |
      |-Interfaces
      |   |
      |   |-Models
      |   |   |
      |       |-Common
      |       |   |-ICommonFunc.cs
      |       |
      |       |-IModelMain.cs
      |       |-IModelOne.cs
      |       |-IModelTwo.cs
      |
      |-Classes
          | 
          |-Models
          |   |
              |-Common
              |   |-CommonFunc.cs
              |
              |-ModelMain.cs
              |-ModelOne.cs
              |-ModelTwo.cs
              |

オプション4-機能の例をさらに取り上げます

MySolution
  |
  |-MyProject
  |   |
      |-Models
      |   |
          |-Components
          |   |
          |   |-Common
          |   |   |
          |   |   |-CommonFunc.cs
          |   |   |-ICommonFunc.cs
          |   |   
          |   |-IModelOne.cs
          |   |-IModelTwo.cs
          |   |-ModelOne.cs
          |   |-ModelTwo.cs
          |
          |-IModelMain.cs
          |-ModelMain.cs
          |

パスにクラス名があるため、オプション1は嫌いです。しかし、私はIoCの選択/使用法(およびは議論の余地があるかもしれない)のため、1:1の比率になる傾向があるため、これにはファイル間の関係を確認する上で利点があります。

オプション2は魅力的ですが、ModelMainとサブモデルの間の水を濁らせました。

オプション3は、インターフェース定義を実装から分離するように機能しますが、パス名にこれらの人為的な区切りがあります。

オプション4。オプション2を採用し、コンポーネントを親モデルから分離するために微調整しました。

どちらか一方を優先する理由はありますか?または私が見逃した他の潜在的なレイアウト?


1.フランクは、1:1の比率が.hおよび.cppファイルのC++日を思い出させるとコメントしました。私は彼がどこから来たのか知っています。 Unityについての私の理解は私をこのコーナーに引き入れているようですが、あなたがProgram to an interfaceしかし、それは別の日の議論です。

2.各オブジェクトコンストラクタの詳細は省略しました。これは、IoCコンテナが必要に応じてオブジェクトを注入する場所です。

18
Peter M

インターフェイスは基本的に基本クラスに似ているため、基本クラスに使用するのと同じロジックを使用します。インターフェイスを実装するクラスは、インターフェイスと密接に関連しています。

「基本クラス」と呼ばれるディレクトリを好むとは思いません。ほとんどの開発者はそれを望んでおらず、「インターフェース」と呼ばれるディレクトリも望まないでしょう。 C#では、ディレクトリはデフォルトで名前空間でもあるため、混乱を招きます。

最善のアプローチは、いくつかを別のライブラリーに入れる必要がある場合にクラス/インターフェースを分割し、同様の方法で名前空間/ディレクトリーを編成する方法を考えることです。 .netフレームワークのデザインガイドラインには 名前空間の提案 があり、参考になることがあります。

5
Frank Hileman

もちろん、2番目のアプローチを採用します。もちろん、複雑なプロジェクトでは、いくつかのフォルダー/名前空間を使用します。それは、具体的な実装からインターフェースを切り離すことを意味します。

別のプロジェクトでは、インターフェースの定義を知る必要があるかもしれませんが、それを実装する具体的なクラスを知る必要はまったくありません。特に、IoCコンテナーを使用する場合はそうです。したがって、これらの他のプロジェクトは、実装プロジェクトではなく、インターフェースプロジェクトのみを参照する必要があります。これにより、参照を低く抑え、循環参照の問題を防ぐことができます。

1
Bernhard Hiller

いつものデザインの質問と同様に、最初に行うことは、ユーザーが誰であるかを決定することです。彼らはあなたの組織をどのように使用するのですか?

彼らはあなたのクラスを使用するコーダーですか?次に、インターフェイスをコードから分離するのが最善の方法です。

彼らはあなたのコードのメンテナーですか?次に、インターフェイスとクラスを一緒にしておくのが最善です。

座って、いくつかのユースケースを作成します。次に、あなたの前に最高の組織が現れるかもしれません。

1
shawnhcorey