7

अभी हम डीआई/आईओसी का उपयोग करते हैं और जब हमें एक निर्माता को अतिरिक्त पैरामीटर पास करने की आवश्यकता होती है तो हम फैक्ट्री क्लास का उपयोग करते हैं।फैक्टरी कक्षाओं के भार लिखने से बचने के लिए कन्स्ट्रक्टर इंजेक्शन के बजाय सर्विसिकेलोकेशन का उपयोग करना बुरा है

public class EmailSender 
{ 
    internal EmailSender(string toEmail, string subject,String body, ILogger emailLogger) 
    {.....} 
} 

public class EmailSenderFactory 
{ 
    ILogger emailLogger; 
    public EmailSenderFactory(ILogger emailLogger) 
    { 
     this.emailLogger = emailLogger; 
    } 
    public EmailSender Create(string toEmail, string subject, string body) 
    { 
     return new EmailSender(toEmail, subject, body, emailLogger); 
    } 
} 

अब इस के साथ समस्या यह है कि हम एक पूरी lotta कारखाने कक्षाएं बनाने अंत है, और लोगों को हमेशा उन्हें इस्तेमाल करना नहीं आता (वे कभी कभी उन्हें खुद को नया)। इस तरह वर्ग कोडिंग की सबसे बड़ी नकारात्मक क्या हैं:

public class EmailSender 
{ 
    EmailLogger logger = IoC.Resolve<ILogger>(); 
    internal EmailSender(string toEmail, string subject,String body) 
    {.....} 
} 

प्रो: अब हम एक कारखाने वर्ग कोन की जरूरत के बिना सुरक्षित रूप से निर्माता का उपयोग कर सकते: हम संदर्भ के लिए सेवा लोकेटर है (मैं के बारे में चिंतित नहीं हूँ टेस्टेबिलिटी, कंटेनर के लिए बैकिंग सेवा के रूप में एक नकली कंटेनर का उपयोग करना आसान है)।

क्या वहां कोई कारण है कि हमें ऐसा क्यों नहीं करना चाहिए?

संपादित करें: सोचा था की एक बिट के बाद, मैं twigged है कि एक निजी निर्माता होने से, और फैक्टरी वर्ग घोंसले बनाने के, मैं कार्यान्वयन और कारखाने एक साथ रह सके, और अनुचित तरीके से कक्षाएं बनाने से लोगों को रोकने, तो सवाल है कुछ हद तक मूक हो जाओ। SL गंदा होने के बारे में सभी बिंदुओं अंक, सच निश्चित रूप से कर रहे हैं, तो नीचे दिए गए समाधान मुझे खुश रखता है:

public class EmailSender 
{ 
    public class Factory 
    { 
     ILogger emailLogger; 
     public Factory(ILogger emailLogger) 
     { 
      this.emailLogger = emailLogger; 
     } 
     public EmailSender Create(string toEmail, string subject, string body) 
     { 
      return new EmailSender(toEmail, subject, body, emailLogger); 
     } 
    } 
    private EmailSender(string toEmail, string subject,String body, ILogger emailLogger) 
    { 
    } 
} 
+0

संपादन पोस्ट करने के लिए धन्यवाद, मुझे इस विचार प्रक्रिया को बहुत उपयोगी लगता है क्योंकि मुझे एक ही चुनौतियों के माध्यम से लगता है। – rohancragg

+0

यह एक उत्कृष्ट सवाल है, और एक जो मुझे नहीं लगता है वास्तव में नीचे सही ढंग से उत्तर दिया गया है। शायद मुझे कुछ याद आ रहा है, लेकिन मैंने केवल ऐसे समाधान देखे हैं जो केंद्रीय रूप से किए गए इंटरफेस को हल करने के समान ही अतिरिक्त कन्स्ट्रक्टर पैराम को केंद्रीय रूप से सेट करने की अनुमति देते हैं। ऊपर वर्णित एक के लिए यह एक बहुत ही अलग स्थिति है, जहां आप सामान्य रूप से पैरा के साथ सीटीआर का उपयोग करने में सक्षम होना चाहते हैं, लेकिन आईएलओगर ऑब्जेक्ट को डीकॉप्लिंग करने का लाभ भी लेना चाहते हैं। मैं केवल यह मान सकता हूं कि इस प्रकार का उपयोग ऐसे परिदृश्यों को सीटी के साथ DI के लिए अनुपयुक्त प्रदान करता है। – Xiaofu

+0

मुझे इंप्रेशन मिल रहा है कि आईओसी का डीआई फॉर्म वास्तव में सच "सेवा घटकों" के लिए आरक्षित होना चाहिए, जिस तरह से आप इसे ऊपर करना चाहते हैं, उसमें कॉन्फ़िगरेशन की आवश्यकता नहीं है। ऐसा कहकर, मुझे अन्यथा दिखाए जाने से प्रसन्नता होगी! :) – Xiaofu

उत्तर

14

हाँ - यह बुरा है।

  • जब आप फ्रेमवर्क काम कर सकते हैं तो वह कोड क्यों लिखें? सभी IoC.Resolve() कॉल अनिवार्य हैं और आपको लिखना नहीं चाहिए।
  • एक और, अधिक महत्वपूर्ण पहलू, यह है कि आपके घटक आपके सेवा लोकेटर से बंधे हैं।

    अब आप उन्हें ऐसे ही का दृष्टांत करने में असमर्थ हैं - आप हर बार जब आप एक घटक का उपयोग करने की जरूरत है स्थान पर एक पूरी तरह से की स्थापना की सेवा लोकेटर की जरूरत है।

  • अंतिम लेकिन, बॉट कम से कम - अपने SL कोड सभी अपने codebase जो एक अच्छी बात नहीं है, क्योंकि जब आप कुछ बदलने के लिए आप कई स्थानों में देखने के लिए करना चाहते हैं के ऊपर छिड़का है।
+0

लेखन 'x = IoC.Resolve ()' कोड मुद्दा मेरे लिए एक गैर-मुद्दा है - यह मुझे फैक्ट्री कक्षाओं का भार लिखने के लिए बचाता है। मेरा एसएल कोड बदलने या कार्यान्वयन से जुड़ा होने की समस्या काफी मामूली है - खासकर यदि मैं http://www.codeplex.com/CommonServiceLocator का उपयोग करता हूं। सबसे बुरी बात यह है कि घटक किसी विशेष एसएल से बंधे हैं, जिसका अर्थ है कि एक कॉलर निर्भरता को नहीं बदल सकता है, इसलिए मैं इसे सबसे अच्छे उत्तर के रूप में स्वीकार करूंगा। – mcintyre321

+4

आपको फैक्ट्री कक्षाएं लिखने की ज़रूरत नहीं है!आईओसी कंटेनर एक कॉन्फ़िगर करने योग्य uberfactory है और यदि आप अपने कोड को सही तरीके से व्यवस्थित करते हैं तो आपको –

+0

की आवश्यकता है और आप अपने कारखाने से सेवाओं को खींचना चाहते हैं (और आप विंडसर का उपयोग कर रहे हैं), आप अभी भी टाइपेड फैक्ट्री सुविधा का उपयोग कर सकते हैं जो आपके कंटेनर द्वारा समर्थित कारखाना http://www.castleproject.org/container/facilities/v1rc3/typedfactory/index.html या ऑटोगेन http://code.google.com/p/castleautogen/ –

2

सबसे बड़ा कारण मैं (सिर्फ सामान्य रूप में सेवा लोकेटर के साथ मुद्दों को देखे बिना) के बारे में सोच सकते हैं कि यह नहीं है कि मैं क्या अपनी कक्षा expect होगा की एक उपयोगकर्ता के रूप में।

मेटा चर्चा:
कुछ डि चौखटे (उदाहरण के लिए Guice) build the factory for you होगा।

कुछ लोग advocate "इंजेक्शन योग्य" से "नया" अलग करते हैं।

+0

@mlk: मूल प्रश्न पर टिप्पणी करने के बाद ही आपके "नए" लिंक को देखा गया। उस के लिए +1, बहुत रोचक। तो ओपी के विशिष्ट परिदृश्य के लिए, क्या आप इसे "इंजेक्शन योग्य" के बजाय "नए" के रूप में वर्गीकृत करेंगे, और इसलिए असुरक्षित या DI का उपयोग करने में असमर्थ? – Xiaofu

+0

मैं ईमानदार होने के लिए पूरी तरह से "लॉगर इंजेक्शन" चीज़ के साथ नहीं जाता हूं। मैं या तो एओपी के लिए नौकरी के रूप में या लॉगिंग ढांचे द्वारा प्रदान किए गए कारखाने से पकड़ने के लिए देखता हूं। ईमेलसेडर मेरे लिए एक विषम वर्ग की तरह seams। मैं इसे दो वर्गों के रूप में देख सकता हूं, ईमेलमैसेज - एक नया और ईमेल सेवा - एक इंजेक्शन योग्य। –

1

मुझे क्रिस्टीज़्टोफ़ द्वारा दिए गए इस मजबूत "यह बुरा है" उत्तर के बारे में पूरी तरह से यकीन नहीं है। मुझे लगता है कि वहां कुछ व्यापार-बंद और वरीयता है, बिना उन्हें बुरी या अच्छी तरह वर्गीकृत किए।

  • मुझे नहीं लगता कि इसे और अधिक ज़रूरत से ज़्यादा इंजेक्शन तंत्र के लिए विशिष्ट कंस्ट्रक्टर्स या गुण लिखने की तुलना में उन IoC.Resolve() कॉल लेखन है।
  • यह एक है, मुझे यह मानना ​​है कि आप एक सेवा लोकेटर से बंधे हैं और आपको कक्षा को स्थापित करने से पहले इसे स्थापित करना होगा। हालांकि:
    • आप अपने सेवा लोकेटर को अधिक विशिष्ट इंटरफेस के साथ अलग कर सकते हैं। इस प्रकार आपके सिस्टम की प्रत्येक सेवाओं के लिए एक विशाल सेवा लोकेटर के साथ युग्मन को कम करना
    • हाँ, यदि आप डी तंत्र का उपयोग करते हैं, तो आप उन सभी IoC.Resolve() को हटा देंगे, लेकिन आपको अभी भी एक प्रकार का कंटेनर तुरंत चालू करना होगा आपकी "मुख्य" सेवाएं। डीआई को उन कॉलों को रोकना है, नहीं?
    • आपकी सेवा लोकेटर (ऑटो? कॉन्फ़िगर करने योग्य "हो सकता है या कम से कम, सेट अप करने में बहुत आसान हो सकता है।
  • "अधिक विशिष्ट इंटरफेस के साथ अपने सेवा लोकेटर को अलग करें ..." बिंदु से ऊपर देखें।

मुझे लगता है कि एक सेवा लोकेटर का उपयोग करना वास्तव में रचनाकारों के माध्यम से उन्हें उजागर करने के बजाय कक्षा के अंदर आपकी निर्भरताओं को छुपा रहा है। और यह मेरी राय में एक असुविधाजनक है क्योंकि आपको पता नहीं चलेगा कि आपकी कक्षा में कुछ याद आ रही है जब तक सेवा लोकेटर को कॉन्फ़िगर किए बिना बुलाया जाता है।

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

लेकिन फिर भी, जब एक वर्ग का परीक्षण किया जाता है जो उसके रचनाकारों पर निर्भरता का पर्दाफाश करता है, तो आप (लगभग) इसे याद नहीं कर सकते हैं। यह सेवा लोकेटर का उपयोग करने का मामला नहीं है।

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

फिल

+2

जब आप DI का उपयोग करके (अंततः) लीगेसी कोड बेस माइग्रेट करने के परिप्रेक्ष्य से देखते हैं तो शायद यह एक (अस्थायी) उपकरण है जिसका उपयोग रास्ते में किया जा सकता है? – rohancragg

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

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