1

私は以下のことを耳にし、この声明を確認するよう求められました。

「SOLID/TDD は 1 つのインターフェースに対して 1 つの実装を推奨していますが、これは現実世界ではなく、インターフェースの要点に反しますよね?」

TDD と DI のすべてのオンライン例はすべて、実装が 1 つしかない典型的な IRepository/MyRepository の例に従っているので、最初は同意しました。さらに考えた後、私は同意しませんでした。

私がやろうとしているのは、そうでないことの証明と、1 つのインターフェイスの複数の実装が存在する可能性がある場所の例を提供し、DI の観点からそれがどのように機能するかを示すことです。

人々がこれで私を助けてくれることを望んでいました。

更新: DI と単体テストの概念は理解していますが、私が示そうとしているのは、1 つのインターフェイスを実装する運用環境で複数のクラスを使用する方法です。

UPDATE2:簡単な例を考えたので、複数の実装の可能な実装を次に示しますが、それでも私が望むものには実際には答えません。ILogger、IDataProvider、または ISomething に単一の依存関係を持つコンストラクターがある場合はどうなるでしょうか。

public interface ILogger
{
  void Write(string data);
}

public class FileLogger : ILogger
{
  void Write(string data)
  {
    //
  }
}

public class DBLogger : ILogger
{
  void Write(string data)
  {
    //
  }
}

public class EventViewerLogger : ILogger
{
  void Write(string data)
  {
    //
  }
}

public class Calculator
{
    private IEnumberable<ILogger> loggers;

    public Calculator(IEnumberable<ILogger> loggers)
    {
        this.loggers = loggers;
    }

    public int Add(int a, int b)
    {
      var result = a + b;

      foreach(var logger in loggers)
      {
        logger.Write("Result was " + logger);
      }
    }
}
4

6 に答える 6

4

いいえ、必要な数の実装を持つことができます。TDD は、インターフェースではなく、実装をテストします。DI は、インターフェースではなく、実装を注入します。複数の実装を持つことができるように、インターフェイスを使用します。

于 2012-08-27T17:06:09.017 に答える
3

テストするときは、通常、インターフェイスのモックを作成して、テスト対象のユニットを分離します。

モックを自分で作成したわけではありませんが、モックはインターフェイスの実装として数えられます。


ここで何を得たいのかわかりません。同じインターフェースの実装が多数あるかどうかは、問題によって異なります。最後に - それは問題ではありません。インターフェイスの利点は、本番環境で同時に複数の実装を行うことができるためではありません。out プロジェクトには多くのインターフェイスがあり、おそらくそれらのほとんどは 1 つの実装しかありません。次の理由から、まだ持っている価値があります。

  • 呼び出し元のコードは実装の数を気にしません->デカップリングを強化します
  • 現在は 1 つの実装しかありませんが、将来別の実装を実装する可能性があります。(YAGNI を考えると、それは弱い議論であることはわかっています)。
  • テストにはモック実装があります
  • 実装を変更することは、別のものを作成するようなものです。複数の実装がありますが、同時にではありません。⇒メンテナンス性が向上します。

要するに、インターフェースの使用を許すために本番環境で多くの実装を行う必要はありません。

于 2012-08-27T17:06:37.023 に答える
2

SOLID は、インターフェイスとクラスの間の 1 対 1 のマッピングを促進しません。

インターフェイスの分離は、取得するインターフェイスに最も近いものです。ただし、できるだけ具体的なインターフェイスを作成する必要があると述べています。Aは(CRUD) と(検索)IUserRepositoryに分解できます。おそらく最初から両方を実装しますが、後で分割します。これの優れた点は、キャッシュされた実装 (デコレータ パターン) を少しの労力で作成したり、書き込みと読み取り (CQRS) に異なるデータ ソースを使用したりできることです。IUserStorageIUserQueriesUserRepository

SOLID に適切に従うと、使いやすく、さまざまな実装を作成できるインターフェイスを備えた、明確に定義された小さなクラスになります。

問題は、SOLID について議論するときに、誰もが典型的なビジネス ロジックだけを考えていることです。しかし、私たちは皆、SOLID が適用されていれば大きなメリットがあるさまざまなフレームワークでコードを実行しています。

私はTDDがあまり得意ではないので、それについてはコメントしません。

于 2012-08-27T18:21:51.227 に答える
1

私はステファンの主張に同意します。テストは本番環境ではないかもしれませんが、アプリケーションの最初の消費者です。

TDD/SOLID が無意味なインターフェースを生成するという議論について、私は 1 つの警告をします: SOLID は抽象化を促進しますが、必ずしもインターフェースではありません。すべてのインターフェイスを作成している場合、これは一部の開発者にとって非常に面倒に思えるかもしれません。インターフェイスは、システムのコンシューマの拡張ポイントである必要があります。テストが主な目的である場合、場合によっては、仮想メソッドを使用する抽象クラスまたは非シール クラスがより適切な場合があります。一部の開発者は、内部クラスの仮想メソッドを、アプリケーションの範囲外では決して使用されないものと見なしています。その主張にはメリットがあるかもしれませんが、これを外部の消費者に拡張する可能性は常にあります。小さな断片に分割することで、拡張とリファクタリングが容易になる可能性があります。そこには' また、手作業でアプリケーションを数時間テストする必要がないことについても言及する必要があります。これは、同僚が進んで行うべき妥協案です。

コア サービスがインスタンスごとにより多くの実装を必要とする開発したアプリケーションはほとんどありませんが、ウェブカメラKinectなどのハードウェア固有の実装を満たすためにさまざまな実装が必要なアプリケーションを開発しました。一度に 1 つしか必要ないかもしれませんが、コンポーネントを組み合わせて一致させる機能は強力です。

複数同時実装に関しては、ストラテジープラグインパターンが人気です。プラグインを介して完全にインターフェースを構成するモジュラーアプリケーション、または構成駆動型の税計算と同じくらい広範囲になる可能性があります。

あなたの例によると、ロギングは多くの場合、混合実装の優れた例です。私はよく log4net を使用して、すべてをファイルに記録し、エラーをイベント ログに記録し、クラッシュをメール アペンダーに記録します。

于 2012-08-27T20:51:36.687 に答える
0

堅実な原則の名前を挙げた(発明者ではない)ボブおじさんには、有名な会計システムの例があります。これは、原則、パターン、および実践の本で見つけることができます。この例では、従業員のリストに基づいてレポートを生成できるクラスがあります。従業員は、時間給の従業員、またはたとえば月給の従業員である可能性があります。それにもかかわらず、彼らは両方とも従業員であり、したがって同じインターフェースを実装します。

于 2012-09-10T17:09:45.867 に答える
0

複数の実装があり、実稼働環境で使用されるインターフェイスの例を探していますか?

JDBC - Oracle、MySql、その他のデータベースには、JDBC インターフェイスの独自の実装があります。

JPA - JPA 実装を参照 - 使用するのに最適なのはどれですか? インターフェイスの実装のリストについては

それとも何か他のものを探していますか?

于 2012-08-27T17:54:03.323 に答える