2008-11-18 21 views
6

en bizYapıcı enjeksiyon ve varsayılan aşırı yükler

public interface ITimestampProvider 
{ 
    DateTime GetTimestamp(); 
} 

ve ona

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(); 
    } 
} 

ve bir varsayılan uygulaması tüketir bir sınıf var diyelim:

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

yararlı veya harfmful mi Bu kurucu tanıtmak için?

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

Bu genel bir sorudur, yani zaman damgası ilgi çekici kısım değildir.

+0

CAB kullanarak hangi bağımlılık bağımlılığı enjeksiyonunu kullanıyorsunuz? Kale? –

+0

Bu sorunun amaçları için, hiçbiri. Genel bir API sorgusudur. "Enjeksiyon" çağrışımını kaldırmak için soruyu güncelledim. –

cevap

7

Bence bu, senaryoya göre değişiyor ve temel olarak, tüketicinin kodun (kitaplığa karşı uygulama) kimin ve bir IoC konteyneri kullanıp kullanmadığının bir işlevi.

  • bir IoC kapsayıcı kullanıyorsanız ve bu halka açık bir API parçası değilse, o zaman konteyner ağır işi yapalım ve sadece tek yapıcı var. Hata ayıklama kurucusunun eklenmesi, asla kullanamayacağınız şeyleri kafa karıştırıcı hale getirir. Bu bir genel API'nin parçasıysa, her ikisini de saklayın. IoC kullanıyorsanız, IoC'nizin "en grevci" yapıcıyı (en argümanlı olanı) bulduğundan emin olun. IoC kullanmıyor, ancak API'nizi kullananlar, nesneyi kullanmak için tüm bağımlılık grafiğini oluşturmaya gerek duymayacaklar.

  • IoC kabı kullanmıyorsanız, ancak yalnızca bir aygıtla birim testi yapmak istiyorsanız, hata ayıklama yapıcısını tutun ve açgözlü yapıcıyı dahili yapın. Açgözlü kurucuyu kullanabilmeniz için ünite test takımınız için InternalsVisibleTo ekleyin. Sadece birim test ediyorsanız, ekstra kamu API yüzeyine ihtiyacınız yoktur.

+0

Bu, bir genel API'nin parçası olacak, bu yüzden aşırı yüklemeyi seçtim. Sadece varsayılanın makul olduğu için bunu düşündüm bile. Tamamen teknik bir endişe için tasarımdan ödün vermekten kaçınmak için sorunun bir IoC vakumda olmasını istedim. –

4

Bu kurucuyu vermem. Bunu yapmak, yeni TimeStamped'i çağırmak ve IoC'niz OtherTimestampProvider() işlevini kullanacak şekilde yapılandırıldığında yeni SystemTimestampProvider() ile bir örnek almak çok kolay hale getirir.

Günün sonunda, yanlış zaman damgasını neden aldığınızın hatalarını ayıklamaya çalışan bir zaman geçecek.

Yalnızca ilk kurucuyu sağlıyorsanız, IoC tarafından yapılandırılmış Sağlayıcı yerine kimin sağlayıcısını (yanlış) kullandığını bulmak için basit bir SystemTimestampProvider kullanımı bulabilirsiniz.

+0

IoC, buradaki senaryonun bir parçası olmasa da, çoğu uygulamanın kayıtlıysa sağlayıcıyı enjekte edeceğini varsayalım, aksi takdirde varsayılan yapıcıyı kullanacağınızı, yani yalnızca 'SystemTimestampProvider' anlamına gelip, 'ITimestampProvider' seçeneğini geçersiz kılmazsanız niyet. Düşünceler? –

3

Genel olarak sanmıyorum ... Bağımlılık Enjeksiyonunu ne kullandığınıza bağlı. Birim testi için DI kullandığımda, enjekte edilen örnek boş olduğunda bağımlı nesnenin üretim sürümünü başlatarak aynı şeyi (daha fazla veya daha az) yapıyorum ... Ve sonra bir parametre ve delegeleri almayan bir aşırı yüküm var. Bunu yapmak için ... Parametrelerini üretim kodu için kullanıyorum ve birim test yöntemleri için bir test sürümü enjekte ediyorum ...

IOC konteyner uygulaması hakkında konuşuyorsanız, ... yapılandırma ayarları net değil bir şekilde yapmak için konteyner anlattığınla müdahale konusunda dikkatli

bunu önlemek için deneyin
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(); 
     } 
    } 
0

- Ben bir olduğunu saptadığımız birkaç yer vardır kullanışlı tasarım ama daha sık t Ben bulamadım, sadece bana biraz şaşıracak hatalar yapmamı sağlar.

Varsayılan olarak enjekte edilen nesnelerin gereksinimi, tüm bu kablolamayı yönetmek için bir bağımlılık enjeksiyon kabı (StructureMap kullanıyorum) kullanılarak büyük ölçüde azaltılır; DI kabı, her zaman kullanabileceğiniz somut bir örnek aldığınızdan emin olur.

Önerdiğiniz kurucuyu kullanmaya hala hevesli olduğum tek yer, birim testlerimdeydi, ancak yakın zamanda sahte veya alaycı nesneler kullanmaktan çok daha fazla değer elde ettim.

Varsayılan bağımlı nesnelere sahip olmanın doğru ve kullanışlı bir tasarım olduğu yerler vardır, ancak genel olarak çok fazla değer eklemeyen sıkı bir bağlantıyı sunduğunuzu söyleyebilirim.

0

Ne yararlı ve ne de zararlı. Estetik bir problem yaratır, çünkü tasarımınız mülk belirleyici enjeksiyonu için izin verdiğinde, DI'nizi yapıcı enjeksiyonuna sınırlandırırsınız.

Diğer bir seçenek varsayılan bir uygulama döndüren bir alıcı uygulamak olacaktır:

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

Alternatif olarak, sen yığın çok fazla nesne oluşturma korkuyorsanız, a tek kullanarak yukarıdaki uygulayabilir.

0

Ekibimin bu yöntemi kullanarak büyük bir başarısı vardır. Bir değişiklik öneriyorum:
_timestampProvider öğesini salt okunur yapın. Bu, sağlayıcıyı inşaatta deterministik olmaya zorlar ve hataları ortadan kaldırır.

public class Timestamped 
{ 
    private readonly ITimestampProvider _timestampProvider; 

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

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

biz DI çerçeveler dahil olmak üzere yeni teknolojilerin, bakarak hep olan Söylediğin. Eğer bu tekniği daha iyi bir şey için terk edersek, size bildiririm.

İlgili konular