2008-11-18 13 views
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; 
    } 
} 

यह उपयोगी या harfmful है इस कन्स्ट्रक्टर को पेश करने के लिए?

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

यह एक सामान्य प्रश्न है, यानी टाइमस्टैम्पिंग दिलचस्प हिस्सा नहीं है।

+0

निर्भरता इंजेक्शन का क्या स्वाद आप सीएबी का उपयोग कर रहे हैं? कैसल? –

+0

इस प्रश्न के प्रयोजनों के लिए, कोई नहीं। यह एक सामान्य एपीआई पूछताछ है। मैंने "इंजेक्शन" अर्थ को हटाने के लिए प्रश्न को अद्यतन किया है। –

उत्तर

7

मुझे लगता है कि यह परिदृश्य पर निर्भर करता है, और मूल रूप से यह एक कार्य है कि उपभोक्ता कोड (लाइब्रेरी बनाम एप्लिकेशन) है और क्या आप आईओसी कंटेनर का उपयोग कर रहे हैं या नहीं।

  • आप एक आईओसी कंटेनर का उपयोग कर रहे हैं, और यह एक सार्वजनिक एपीआई का हिस्सा नहीं है, तो कंटेनर भार उठाने करते हैं, और सिर्फ एक निर्माता है। नो-Args कन्स्ट्रक्टर जोड़ना सिर्फ चीजों को भ्रमित कर देता है, क्योंकि आप इसका कभी भी उपयोग नहीं करेंगे।

  • यदि यह सार्वजनिक एपीआई का हिस्सा है, तो दोनों को रखें। यदि आप आईओसी का उपयोग कर रहे हैं, तो बस सुनिश्चित करें कि आपके आईओसी को "लालची" कन्स्ट्रक्टर (सबसे अधिक तर्क वाले वाला) मिल जाए। लोग आईओसी का उपयोग नहीं कर रहे हैं, लेकिन आपके एपीआई का उपयोग करने से आपकी ऑब्जेक्ट का उपयोग करने के लिए एक संपूर्ण निर्भरता ग्राफ बनाने की सराहना नहीं होगी।

  • यदि आप आईओसी कंटेनर का उपयोग नहीं कर रहे हैं, लेकिन सिर्फ एक नकली के साथ यूनिट परीक्षण करना चाहते हैं, नो-Args कन्स्ट्रक्टर रखें, और लालची कन्स्ट्रक्टर आंतरिक बनाएं। अपनी इकाई परीक्षण असेंबली के लिए InternalsVisibleTo जोड़ें ताकि वह लालची कन्स्ट्रक्टर का उपयोग कर सके। यदि आप केवल यूनिट परीक्षण कर रहे हैं, तो आपको अतिरिक्त सार्वजनिक API सतह की आवश्यकता नहीं है।

+0

यह एक सार्वजनिक एपीआई का हिस्सा होगा, इसलिए मैंने अधिभार को रखने के लिए चुना है। केवल इसलिए कि डिफ़ॉल्ट उचित है क्या मैंने इसे भी माना। मैं पूरी तरह से तकनीकी चिंता के लिए समझौता डिजाइन से बचने के लिए सवाल आईओसी वैक्यूम में होना चाहता था। –

4

मैं कि निर्माता प्रदान नहीं करेगी। ऐसा करने से नया टाइमस्टैम्पड कॉल करना बहुत आसान हो जाता है और जब आप अपने आईओसी को अन्य टिमस्टैम्पप्रोवाइडर() का उपयोग करने के लिए कॉन्फ़िगर किया जा सकता है तो नए सिस्टम टिमस्टैम्पप्रोवाइडर() के साथ एक उदाहरण प्राप्त करें।

दिन के अंत आप एक समय क्यों तुम गलत टाइमस्टैम्प हो रही है डिबग करने के लिए कोशिश कर रहा से एक नरक के साथ खत्म हो जाएगा।

यदि आप केवल पहले कन्स्ट्रक्टर प्रदान करते हैं तो आप IoC कॉन्फ़िगर प्रदाता के बजाय उस प्रदाता का उपयोग करने वाले (गलत तरीके से) का पता लगाने के लिए SystemTimestampProvider के उपयोग को सरल बना सकते हैं।

+0

हालांकि आईओसी यहां परिदृश्य का हिस्सा नहीं है, लेकिन मुझे लगता है कि अधिकांश कार्यान्वयन प्रदाता को इंजेक्ट करते हैं, अन्यथा डिफॉल्ट कन्स्ट्रक्टर का उपयोग करते हैं, जिसका अर्थ है कि आपको केवल 'SystemTimestampProvider'' मिलेगा यदि आपने 'ITimestampProvider' को ओवरराइड नहीं किया है, जो सटीक है आशय। विचार? –

3

सामान्य तौर पर मैं ऐसा नहीं सोचता ... यह क्या आप के लिए निर्भरता इंजेक्शन का उपयोग कर रहे पर निर्भर करता है। जब मैं इकाई परीक्षण के लिए DI का उपयोग करता हूं, तो इंजेक्शन उदाहरण शून्य होने पर मैं निर्भर वस्तु के उत्पादन संस्करण को तुरंत चालू करके एक ही चीज़ (अधिक या कम) करता हूं ... और फिर मेरे पास एक अधिभार है जो पैरामीटर और प्रतिनिधि नहीं लेता है जो करता है ... मैं उत्पादन कोड के लिए पैरामीटर रहित का उपयोग करता हूं, और इकाई परीक्षण विधियों के लिए एक परीक्षण संस्करण इंजेक्ट करता हूं ...

यदि आप किसी आईओसी कंटेनर एप्लिकेशन के बारे में बात कर रहे हैं, तो आपको होना चाहिए क्या विन्यास सेटिंग्स कंटेनर एक तरीका है कि स्पष्ट नहीं है में करने के लिए कह रहे हैं में हस्तक्षेप के बारे में सावधान ...

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

मैं इस से बचने की कोशिश - कुछ स्थानों पर जहां मैं इसे एक होने के लिए मिल गया है देखते हैं उपयोगी डिजाइन लेकिन अधिक बार टी हां नहीं, मैंने पाया है कि यह मुझे गलतियाँ करने की ओर ले जाता है जो काम करने के लिए थोड़ा परेशान हो सकता है।

इन सभी तारों को प्रबंधित करने के लिए एक निर्भरता इंजेक्शन कंटेनर (मैं स्ट्रक्चर मैप का उपयोग करके) डिफ़ॉल्ट इंजेक्शन ऑब्जेक्ट्स की आवश्यकता बहुत कम हो जाती है - डी कंटेनर यह सुनिश्चित करता है कि आप हमेशा एक ठोस उदाहरण प्राप्त कर सकें जिसका आप उपयोग कर सकते हैं।

केवल जगह है जहाँ मैं अभी भी निर्माता सुझाव का उपयोग करने के लिए परीक्षा रहा हूँ मेरी इकाई परीक्षण में है, लेकिन हाल ही में मैं नकली या मज़ाक उड़ाया वस्तुओं का उपयोग कर से बाहर अब तक अधिक से अधिक मूल्य मिल रहा है।

स्थान हैं जहां डिफ़ॉल्ट निर्भर वस्तुओं होने सही और उपयोगी डिजाइन है, लेकिन सामान्य रूप में मैं कहेंगे कि आप बस तंग युग्मन कि मूल्य का एक बहुत नहीं जोड़ता है शुरू कर रहे हैं।

0

यह न तो उपयोगी है और न ही हानिकारक है। यह एक सौंदर्य समस्या है कि आप अपने डी को केवल कन्स्ट्रक्टर इंजेक्शन तक ही सीमित कर रहे हैं जब आपका डिज़ाइन प्रॉपर्टी सेटर इंजेक्शन के लिए अनुमति दे सकता है।

एक अन्य विकल्प गेटर एक डिफ़ॉल्ट कार्यान्वयन देता है कि लागू करने के लिए होगा:

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

वैकल्पिक रूप से, आप एक सिंगलटन का उपयोग कर यदि आप ढेर में ऐसे अनेक वस्तुओं बनाने के बारे में चिंतित हैं ऊपर लागू कर सकते हैं।

0

मेरी टीम के पास इस विधि का उपयोग करके सफलता का एक बड़ा सौदा है। मैं एक बदलाव की सिफारिश करता हूं:
_timestampProvider को केवल पढ़ने के लिए बनाओ। यह प्रदाता को निर्माण पर निर्धारक होने के लिए मजबूर करता है और बग को खत्म कर देगा।

public class Timestamped 
{ 
    private readonly ITimestampProvider _timestampProvider; 

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

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

कहा यही कारण है, हम कर रहे हैं हमेशा डि चौखटे सहित नई प्रौद्योगिकियों, पर देख रहे हैं। अगर हम कभी भी इस तकनीक को कुछ बेहतर तरीके से छोड़ देते हैं तो मैं आपको बता दूंगा।

संबंधित मुद्दे