6

私たちが持っているとしましょう

public interface ITimestampProvider
{
    DateTime GetTimestamp();
}

そしてそれを消費するクラス

public class Timestamped
{
    private ITimestampProvider _timestampProvider

    public Timestamped(ITimestampProvider timestampProvider)
    {
        // arg null check

        _timestampProvider = timestampProvider;
    }

    public DateTime Timestamp { get; private set; }

    public void Stamp()
    {
        this.Timestamp = _timestampProvider.GetTimestamp();
    }
}

およびデフォルトの実装:

public sealed class SystemTimestampProvider : ITimestampProvider
{
    public DateTime GetTimestamp()
    {
        return DateTime.Now;
    }
}

このコンストラクターを導入することは役に立ちますか、それとも有害ですか?

public Timestamped() : this(new SystemTimestampProvider())
{}

これは一般的な質問です。つまり、タイムスタンプは興味深い部分ではありません。

4

6 に答える 6

7

それはシナリオに依存すると思いますが、基本的には、コードの消費者 (ライブラリとアプリケーション) と、IoC コンテナーを使用しているかどうかの関数です。

  • IoC コンテナーを使用していて、これがパブリック API の一部ではない場合は、コンテナーに面倒な作業を任せて、コンストラクターを 1 つだけにします。引数なしのコンストラクターを追加すると、決して使用しないため、混乱が生じるだけです。

  • これがパブリック API の一部である場合は、両方を保持してください。IoC を使用している場合は、IoC が「貪欲な」コンストラクター (引数が最も多いコンストラクター) を見つけるようにしてください。IoC を使用していないが、API を使用している人は、オブジェクトを使用するために依存関係グラフ全体を構築する必要がないことに感謝します。

  • IoC コンテナーを使用していないが、モックを使用して単体テストを行いたい場合は、引数なしのコンストラクターを保持し、貪欲なコンストラクターを内部にします。貪欲なコンストラクターを使用できるように、単体テスト アセンブリに InternalsVisibleTo を追加します。単体テストのみを行う場合は、追加のパブリック API サーフェスは必要ありません。

于 2008-11-18T22:35:18.120 に答える
4

私はそのコンストラクターを提供しません。そうすることで、IoCがOtherTimestampProvider()を使用するように構成されている場合に、新しいTimeStampedを呼び出して、新しいSystemTimestampProvider()でインスタンスを取得することが非常に簡単になります。

1日の終わりに、間違ったタイムスタンプを取得している理由をデバッグしようとすると、1つの時間の地獄になってしまいます。

最初のコンストラクターのみを提供する場合は、SystemTimestampProviderの簡単な検索の使用法を実行して、IoCで構成されたプロバイダーの代わりにそのプロバイダーを(誤って)使用しているユーザーを見つけることができます。

于 2008-11-18T22:03:42.287 に答える
3

一般的に私はそうは思いません...それはあなたが依存性注入を何のために使っているかによります。単体テストにDIを使用する場合、注入されたインスタンスがnullのときに依存オブジェクトの本番バージョンをインスタンス化することで同じことを(多かれ少なかれ)行います...そして、パラメーターを受け取らずに委任するオーバーロードがありますパラメータのないものを本番コードに使用し、単体テストメソッドのテストバージョンを注入します...

IOCコンテナアプリケーション、otohについて話している場合は、構成設定がコンテナに明確でない方法で実行するように指示していることに干渉することに注意する必要があります...

   public class EventsLogic
   { 
       private readonly IEventDAL ievtDal;
       public IEventDAL IEventDAL { get { return ievtDal; } }

       public EventsLogic(): this(null) {}
       public EventsLogic(IIEEWSDAL wsDal, IEventDAL evtDal)
       {
          ievtDal = evtDal ?? new EventDAL();
       }
    }
于 2008-11-18T22:04:09.757 に答える
0

私のチームは、この方法を使用して大きな成功を収めています。1つの変更をお勧めします:
_timestampProviderを読み取り専用にします。これにより、プロバイダーは構築時に決定論的になり、バグが排除されます。

public class Timestamped
{
    private readonly ITimestampProvider _timestampProvider;

    public Timestamped(ITimestampProvider timestampProvider)
    {
        _timestampProvider = timestampProvider;
    }

    public Timestamped(): this(new SystemTimestampProvider())
    { }
}

そうは言っても、私たちは常にDIフレームワークを含む新しいテクノロジーを検討しています。このテクニックを大幅に改善するために放棄した場合は、お知らせします。

于 2008-11-18T23:01:56.147 に答える
0

私はこれを避けようとしています-それが便利なデザインであることがわかった場所がいくつかありますが、多くの場合、それは私がうまくいくのに少し困惑する可能性のある間違いを犯すことにつながることがわかりました。

依存性注入コンテナ(私はStructureMapを使用)を使用してこのすべての配線を管理することにより、デフォルトの注入オブジェクトの必要性が大幅に減少します。DIコンテナにより、使用できる具体的なインスタンスを常に取得できます。

あなたが提案するコンストラクターをまだ使いたくなる唯一の場所は、単体テストですが、最近、偽のオブジェクトやモックオブジェクトを使用することではるかに大きな価値を得ています。

デフォルトの依存オブジェクトを使用することが正しくて便利な設計である場合もありますが、一般的には、あまり価値のない密結合を導入しているだけだと思います。

于 2008-11-18T22:08:15.240 に答える
0

それは役に立たず、有害でもありません。デザインでプロパティセッターインジェクションが許可されている場合にのみ、DIをコンストラクターインジェクションに制限するという美的問題が発生します。

別のオプションは、デフォルトの実装を返すゲッターを実装することです。

public DateTime Timestamp
{
    get { return _timestampProvider??new SystemTimestampProvider(); }
    set { _timestampProvider = value; }
}

または、ヒープ内に作成するオブジェクトが多すぎることが心配な場合は、シングルトンを使用して上記を実装できます。

于 2008-11-18T22:08:40.483 に答える