Init () विधियाँ एक कोड गंध हैं?


20

क्या किसी init()प्रकार के लिए एक विधि घोषित करने का कोई उद्देश्य है ?

मैं यह नहीं पूछ रहा हूं कि हमें किसी कंस्ट्रक्टर के ऊपर पसंदinit() करना चाहिए या घोषणा करने से कैसे बचना चाहिएinit()

मैं पूछ रहा हूं कि क्या कोई विधि घोषित करने के पीछे कोई तर्क है init()(यह देखना कि यह कितना सामान्य है) या यदि यह एक कोड गंध है और इसे टाला जाना चाहिए।


init()मुहावरा बहुत आम है, लेकिन मैं अभी तक किसी भी वास्तविक लाभ प्राप्त करना है।

मैं उन तरीकों के बारे में बात कर रहा हूं जो एक विधि के माध्यम से आरंभ को प्रोत्साहित करते हैं:

class Demo {
    public void init() {
        //...
    }
}

यह उत्पादन कोड में कब इस्तेमाल होगा?


मुझे लगता है कि यह एक कोड गंध हो सकता है क्योंकि यह सुझाव देता है कि निर्माता पूरी तरह से ऑब्जेक्ट को इनिशियलाइज़ नहीं करता है, जिसके परिणामस्वरूप आंशिक रूप से बनाई गई ऑब्जेक्ट है। यदि स्थिति सेट नहीं है, तो ऑब्जेक्ट मौजूद नहीं होना चाहिए।

यह मुझे विश्वास दिलाता है कि यह उद्यम अनुप्रयोगों के अर्थ में उत्पादन को गति देने के लिए इस्तेमाल की जाने वाली कुछ प्रकार की तकनीक का हिस्सा हो सकता है। यह केवल एक तार्किक कारण है कि मैं इस तरह के मुहावरे के बारे में सोच सकता हूं, मुझे यकीन नहीं है कि यदि ऐसा है तो यह कैसे फायदेमंद होगा।


1
"... यह देखना कितना आम है ...": क्या यह आम है? क्या आप कुछ उदाहरण दे सकते हैं? शायद आप एक ऐसे ढांचे के साथ काम कर रहे हैं जिसके लिए आरंभीकरण और निर्माण को अलग करना आवश्यक है।
आया

क्या विधि एक आधार वर्ग या एक व्युत्पन्न वर्ग, या दोनों पर पाई जाती है? (या: एक वर्ग पर पाई जाने वाली विधि है जो एक वंशानुगत पदानुक्रम से संबंधित है? क्या बेस क्लास init()व्युत्पन्न वर्ग पर कॉल करता है , या इसके विपरीत?) यदि हां, तो यह बेस क्लास को "पोस्ट-कंस्ट्रक्टर" निष्पादित करने का एक उदाहरण है। "जिसे केवल सबसे व्युत्पन्न वर्ग के निर्माण के बाद निष्पादित किया जा सकता है। यह बहु-चरण आरंभीकरण का एक उदाहरण है।
रवांग

यदि आप तात्कालिकता के बिंदु पर आरंभ नहीं करना चाहते हैं, तो यह दोनों को अलग करने के लिए समझ में आएगा।
J --M।

आपकी रुचि हो सकती है।
इज़

जवाबों:


39

हाँ, यह एक कोड गंध है। एक कोड गंध कुछ ऐसा नहीं है जो जरूरी है कि हमेशा हटाया जाना चाहिए। यह ऐसा कुछ है जो आपको एक दूसरा रूप देता है।

यहां आपको दो अलग-अलग राज्यों में एक वस्तु है: प्री-इनिट और पोस्ट-इनिट। उन राज्यों की अलग-अलग ज़िम्मेदारियाँ हैं, अलग-अलग तरीके जिन्हें कॉल करने की अनुमति है, और अलग-अलग व्यवहार। यह प्रभावी रूप से दो अलग-अलग वर्ग है।

यदि आप शारीरिक रूप से उन्हें दो अलग-अलग वर्ग बनाते हैं, तो आप सांख्यिकीय रूप से संभावित बगों की एक पूरी कक्षा को हटा देंगे, हो सकता है कि आपके मॉडल को "वास्तविक दुनिया के मॉडल" से बहुत करीब से मेल न खाएं। आप आम तौर पर पहले एक नाम Configया Setupया ऐसा ही कुछ।

इसलिए अगली बार, अपने निर्माण-init मुहावरों को दो-श्रेणी के मॉडल में बदलने का प्रयास करें और देखें कि यह आपके लिए कैसा है।


6
टू-क्लास मॉडल को आज़माने का आपका सुझाव अच्छा है। कोड-गंध को संबोधित करने के लिए एक ठोस कदम का प्रस्ताव उपयोगी है।
इवान

1
यह अब तक का सबसे अच्छा जवाब है। हालाँकि एक बात मुझे परेशान करती है: " उन राज्यों की अलग-अलग ज़िम्मेदारियाँ होती हैं, अलग-अलग तरीके जिन्हें कॉल करने की अनुमति होती है, और अलग व्यवहार " - इन जिम्मेदारियों को अलग नहीं करना एसआरपी का उल्लंघन करता है। यदि सॉफ़्टवेयर का उद्देश्य हर पहलू में एक वास्तविक विश्व परिदृश्य को दोहराने के लिए था, तो इसका मतलब होगा। लेकिन उत्पादन में, देव ज्यादातर कोड लिखते हैं जो आसान प्रबंधन को प्रोत्साहित करते हैं, मॉडल को संशोधित करते हैं यदि सॉफ़्टवेयर-आधारित एनवायरनमेंट को बेहतर ढंग से फिट करने की आवश्यकता होती है (अगली टिप्पणी पर जारी रखें)
विंस एमिग

1
वास्तविक दुनिया एक अलग वातावरण है। इसे दोहराने का प्रयास करने वाले कार्यक्रम डोमेन विशिष्ट प्रतीत होते हैं, क्योंकि आप अधिकांश परियोजनाओं में इसके लिए जिम्मेदार नहीं होंगे। जब डोमेन विशिष्ट परियोजनाओं की बात आती है, तो बहुत सी चीज़ों को स्वीकार कर लिया जाता है, इसलिए मैं इसे यथासंभव सामान्य रखने की कोशिश कर रहा हूं (जैसे thisकि कंस्ट्रक्टर में कॉल करना एक कोड गंध है और परिणामस्वरूप त्रुटि-कोड हो सकता है, और इससे बचना अनुशंसित है कि आपकी परियोजना किस क्षेत्र में आती है, इसकी परवाह किए बिना)।
विंस एमघे

14

निर्भर करता है।

एक initविधि एक कोड गंध है जब यह आवश्यक नहीं है कि ऑब्जेक्ट इनिशियलाइज़ेशन को कंस्ट्रक्टर से अलग किया जाए। कभी-कभी ऐसे मामले होते हैं जहां यह इन चरणों को अलग करने के लिए समझ में आता है।

एक त्वरित Google खोज ने मुझे यह उदाहरण दिया। मैं आसानी से और अधिक मामलों की कल्पना कर सकता हूं जहां ऑब्जेक्ट आवंटन (निर्माणकर्ता) के दौरान निष्पादित कोड बेहतर हो सकता है कि उसे प्रारंभ से ही अलग कर दिया जाए। हो सकता है कि आपके पास एक स्तरित प्रणाली है, और आवंटन / निर्माण स्तर X में होता है, लेकिन प्रारंभिक स्तर Y में केवल इसलिए, क्योंकि केवल Y ही आवश्यक पैरामीटर प्रदान कर सकता है। हो सकता है कि "init" महंगा हो और केवल आबंटित वस्तुओं के सबसेट के लिए चलाया जाना चाहिए, और उस उपसमुच्चय का निर्धारण केवल लेवल Y में किया जा सकता है। या आप व्युत्पन्न में आभासी (आभासी) "init" विधि को ओवरराइड करना चाहते हैं क्लास जिसे कंस्ट्रक्टर के साथ नहीं किया जा सकता है। हो सकता है कि स्तर X आपको एक विरासत पेड़ से आवंटित वस्तुओं के साथ प्रदान करता है, लेकिन स्तर वाई कंक्रीट व्युत्पत्ति के बारे में नहीं जानता है, केवल सामान्य इंटरफ़ेस के बारे में (जहां)init शायद परिभाषित)।

बेशक, मेरे अनुभव से ये मामले मानक मामले का केवल एक छोटा प्रतिशत हैं, जहां सभी आरंभीकरण सीधे निर्माणकर्ता में किया जा सकता है, और जब भी आप एक अलग initविधि देखते हैं , तो इसकी आवश्यकता पर सवाल उठाना एक अच्छा विचार हो सकता है।


2
उस लिंक में उत्तर कहता है कि यह कंस्ट्रक्टर में काम की मात्रा को कम करने के लिए उपयोगी है, लेकिन यह आंशिक रूप से निर्मित वस्तुओं को प्रोत्साहित करता है। छोटे कंस्ट्रक्टरों को अपघटन के माध्यम से प्राप्त किया जा सकता है, इसलिए मुझे ऐसा लगता है कि उत्तर एक नई समस्या पैदा करते हैं (सभी आवश्यक आरंभीकरण विधियों को कॉल करने के लिए भूल जाते हैं, ऑब्जेक्ट त्रुटि-प्रवण को छोड़कर) और कोड गंध श्रेणी के अंतर्गत आता है
विंस जांघ

@VinceEmigh: ठीक है, यह पहला उदाहरण मैं यहाँ एसई platfform पर मिल सकता है, शायद नहीं सबसे अच्छा एक था, लेकिन वहाँ रहे हैं एक अलग के लिए वैधानिक उपयोग के मामले initविधि। हालांकि, जब भी आप इस तरह की विधि देखते हैं, तो इसकी आवश्यकता पर सवाल उठाने के लिए स्वतंत्र महसूस करें।
डॉक्टर ब्राउन 6

मैं इसके लिए हर उपयोग के मामले में पूछताछ / चुनौती दे रहा हूं, क्योंकि मुझे लगता है कि ऐसी कोई स्थिति नहीं है जहां यह एक आवश्यकता होगी। मेरे लिए, यह ऑब्जेक्ट निर्माण का खराब समय है, और इसे टाला जाना चाहिए क्योंकि यह त्रुटियों के लिए एक उम्मीदवार है जिसे उचित डिजाइन के माध्यम से टाला जा सकता है। यदि किसी init()विधि का उचित उपयोग होता है , तो मुझे यकीन है कि मैं इस उद्देश्य के बारे में सीखने से लाभान्वित होऊंगा। मेरी अज्ञानता को माफ कीजिए, मैं बस इस बात से चकित हूं कि मैं कितने समय से इसके लिए उपयोग कर रहा हूं, मुझे इस पर विचार करने से रोक रहा है कि इससे बचना चाहिए
विंस एमिग

1
@VinceEmigh: जब आप ऐसी स्थिति के बारे में सोच नहीं सकते हैं, तो आपको अपनी कल्पना पर काम करने की आवश्यकता है; ;-) या मेरे उत्तर को फिर से पढ़ें, इसे केवल "आवंटन" के लिए कम न करें। या विभिन्न विक्रेताओं से अधिक रूपरेखा के साथ काम करते हैं।
डॉक ब्राउन

1
@DocBrown सिद्ध प्रथाओं के बजाय कल्पना का उपयोग करते हुए कुछ कायरता कोड की ओर जाता है, जैसे कि डबल ब्रेस इनिशियलाइज़ेशन: चतुर, लेकिन अक्षम और इससे बचा जाना चाहिए। मुझे पता है कि विक्रेता इसका उपयोग करते हैं, लेकिन इसका मतलब यह नहीं है कि उपयोग उचित है। अगर आपको ऐसा लगता है, तो कृपया मुझे बताएं कि मैं ऐसा क्यों कर रहा हूं। आपको लग रहा था कि इस पर कुछ लाभकारी उद्देश्य है, लेकिन ऐसा लगता है कि आपको एक कठिन समय एक उदाहरण दे रहा है जो अच्छे डिजाइन को प्रोत्साहित करता है। मुझे पता है कि किन परिस्थितियों में इसका इस्तेमाल किया जा सकता है, लेकिन क्या इसका इस्तेमाल किया जाना चाहिए ?
विंस एमिघ

5

मेरा अनुभव दो समूहों में टूट जाता है:

  1. कोड जहां init () वास्तव में आवश्यक है। यह तब हो सकता है जब एक सुपरक्लास या ढांचा आपके वर्ग के निर्माता को निर्माण के दौरान उसकी सभी निर्भरता प्राप्त करने से रोकता है।
  2. कोड जहां init () का उपयोग किया जाता है लेकिन उसे टाला जा सकता था।

अपने व्यक्तिगत अनुभव में मैंने (1) के कुछ उदाहरणों (2) के कई उदाहरणों को देखा है। नतीजतन, मैं आमतौर पर एक init () एक कोड-गंध मान रहा हूं, लेकिन यह हमेशा ऐसा नहीं होता है। कभी-कभी आप बस इसके आसपास नहीं पहुंच सकते।

मैंने पाया है कि बिल्डर पैटर्न का उपयोग अक्सर एक इनिट () करने की आवश्यकता / इच्छा को दूर करने में मदद कर सकता है।


1
यदि एक सुपरक्लास या फ्रेमवर्क एक प्रकार को निर्भरता हासिल करने की अनुमति नहीं देता है, तो उसे निर्माता के माध्यम से इसकी आवश्यकता कैसे होती है, एक init()विधि इसे कैसे जोड़ सकती है? init()विधि या तो निर्भरता स्वीकार करने के लिए मानकों की आवश्यकता होगी, या आप निर्भरता का दृष्टांत होगा भीतरinit() विधि है, जो आप भी एक निर्माता के साथ कर सकता। क्या आप एक उदाहरण दे सकते हैं?
विंस एमघे

1
@VinceEmigh: init () का उपयोग कभी-कभी किसी बाहरी स्रोत से कॉन्फ़िग फ़ाइल लोड करने, डेटाबेस कनेक्शन खोलने या उस ilk के कुछ करने के लिए किया जा सकता है। DoFn.initialize () विधि (अपाचे क्रंच फ्रेमवर्क से) का उपयोग इस तरीके से किया जाता है। इसका उपयोग गैर-क्रमिक आंतरिक क्षेत्रों को लोड करने के लिए भी किया जा सकता है (DoFns को serializable होना चाहिए)। यहाँ दो समस्याएं यह है कि (1) कुछ को सुनिश्चित करने की आवश्यकता है कि इनिशियलाइज़ मेथड कहा जाता है और (2) ऑब्जेक्ट को यह पता होना चाहिए कि यह उन संसाधनों को कहाँ (या कैसे बनाने जा रहा है)।
इवान

1

जब एक इनिट विधि काम आती है तो एक विशिष्ट परिदृश्य तब होता है जब आपके पास एक कॉन्फ़िगरेशन फ़ाइल होती है जिसे आप बदलना चाहते हैं और एप्लिकेशन को पुनरारंभ किए बिना परिवर्तन को ध्यान में रखना है। यह, ज़ाहिर है, इसका मतलब यह नहीं है कि एक Init विधि को एक निर्माता से अलग से बुलाया जाना चाहिए। आप एक कंस्ट्रक्टर से एक Init मेथड को कॉल कर सकते हैं, और फिर कॉन्फ़िगरेशन पैरामीटर में बदलाव होने पर इसे बाद में कॉल कर सकते हैं।

योग करने के लिए: अधिकांश दुविधाओं के लिए, चाहे वह कोड गंध हो या न हो, स्थिति और परिस्थितियों पर निर्भर करता है।


विन्यास अद्यतन, और इस रीसेट करने के लिए वस्तु की आवश्यकता है / विन्यास के आधार पर यह स्थिति बदलने, आपको नहीं लगता कि यह बेहतर एक के रूप में वस्तु अधिनियम के लिए किया जाएगा पर्यवेक्षक की ओर Config?
विंस एमघे

@ विंस एमिह नॉटिलरिली। यदि मैं कॉन्फ़िगरेशन को बदलता है, तो मैं सटीक क्षण जानता हूं, तो पर्यवेक्षक काम करेगा। हालाँकि, यदि कॉन्फ़िगरेशन डेटा को एक फ़ाइल में रखा जाता है जिसे किसी एप्लिकेशन के बाहर बदला जा सकता है, तो वास्तव में कोई अतिरिक्त दृष्टिकोण नहीं है। उदाहरण के लिए, अगर मेरे पास एक प्रोग्राम है जो कुछ फ़ाइलों को पार्स करता है और डेटा को कुछ आंतरिक मॉडल में बदल देता है, और एक अलग कॉन्फ़िगरेशन फ़ाइल में लापता डेटा के लिए डिफ़ॉल्ट मान होते हैं, अगर मैं डिफ़ॉल्ट मानों को बदल देता हूं, तो मैं उन्हें फिर से पढ़ूंगा जब मैं अगली बार चलाऊंगा पार्सिंग। मेरे आवेदन में एक Init पद्धति का होना उस मामले में काफी उपयोगी होगा।
व्लादिमीर स्टोकिक

यदि कॉन्फ़िगरेशन फ़ाइल को बाह्य रूप से रनटाइम पर संशोधित किया जाता है, तो आपके एप्लिकेशन को सूचित किए बिना किसी प्रकार की अधिसूचना के बिना उन चर को फिर से लोड करने का कोई तरीका नहीं है कि यह init को कॉल करने की आवश्यकता है ( update/ reloadशायद इस तरह के व्यवहार के लिए अधिक वर्णनात्मक होगा) वास्तव में उन परिवर्तनों को। । उस स्थिति में, उस अधिसूचना के कारण आपके एप्लिकेशन में आंतरिक रूप से कॉन्फ़िगरेशन के मान बदल जाएंगे, जो मुझे लगता है कि आपके कॉन्‍फ़ि‍गर होने का अवलोकन किया जा सकता है, जब वे मानों में से एक को परिवर्तित करने के लिए कहा जाता है, तो वे पर्यवेक्षकों को सूचित करते हैं। या मैं आपके उदाहरण को गलत समझ रहा हूं?
विन्स एमघे

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

1

निर्भर करता है कि आप उनका उपयोग कैसे करते हैं।

मैं जावा / सी # जैसी कचरा एकत्र की गई भाषाओं में उस पैटर्न का उपयोग करता हूं, जब मैं हीप पर ऑब्जेक्ट को पुन: प्रदर्शित नहीं करना चाहता हूं (जैसे जब मैं वीडियो गेम बना रहा हूं और प्रदर्शन उच्च रखने की आवश्यकता है, तो कचरा कलेक्टर प्रदर्शन को मारते हैं)। मैं निर्माणकर्ता का उपयोग अन्य ढेर आवंटन initबनाने के लिए करता हूं , जो इसकी आवश्यकता है, और हर बार जब मैं इसका पुन: उपयोग करना चाहता हूं, उससे पहले मूल उपयोगी स्थिति बनाने के लिए। यह ऑब्जेक्ट पूल की अवधारणा से संबंधित है।

यह भी उपयोगी है यदि आपके पास कई निर्माता हैं जो प्रारंभिक निर्देश के एक सामान्य सबसेट को साझा करते हैं, लेकिन उस मामले initमें निजी होगा। इस तरह मैं प्रत्येक निर्माता को जितना संभव हो उतना कम से कम कर सकता हूं, इसलिए प्रत्येक को केवल अपने अनूठे निर्देश और initबाकी को करने के लिए एक ही कॉल होता है।

सामान्य तौर पर, यह एक कोड गंध है।


क्या reset()आपके पहले कथन के लिए कोई विधि अधिक वर्णनात्मक नहीं होगी? दूसरे (कई कंस्ट्रक्टर) के रूप में, कई कंस्ट्रक्टर होने से एक कोड गंध है। यह मानता है कि एसआरपी उल्लंघन का सुझाव देते हुए ऑब्जेक्ट के कई उद्देश्य / जिम्मेदारियां हैं। एक ऑब्जेक्ट में एक जिम्मेदारी होनी चाहिए, और निर्माता को उस एक जिम्मेदारी के लिए आवश्यक निर्भरता को परिभाषित करना चाहिए। यदि आपके पास वैकल्पिक मानों के कारण कई निर्माता हैं, तो उन्हें दूरबीन चाहिए (जो कोड गंध भी है, इसके बजाय एक बिल्डर का उपयोग करना चाहिए)।
विंस एमघे

@VinceEmigh आप init या रीसेट का उपयोग कर सकते हैं, यह केवल एक नाम है। Init उस संदर्भ में अधिक अर्थ रखता है जिसका मैं उपयोग करता हूं क्योंकि यह उस वस्तु को रीसेट करने के लिए बहुत कम समझ में आता है जो पहली बार उपयोग करने के बाद कभी सेट नहीं किया गया था। निर्माता के मुद्दे के रूप में, मैं बहुत सारे निर्माणकर्ताओं से बचने की कोशिश करता हूं, लेकिन कभी-कभी यह मददगार होता है। किसी भी भाषा की stringनिर्माता सूची, विकल्पों के टन को देखें। मेरे लिए आमतौर पर यह शायद 3 कंस्ट्रक्टर अधिकतम है, लेकिन निर्देशन के सामान्य सबसेट के रूप में इनिशियलाइज़ेशन का अर्थ है जब वे किसी भी कोड को साझा करते हैं लेकिन किसी भी तरह से भिन्न होते हैं।
कोडी

नाम अत्यंत महत्वपूर्ण हैं। वे ग्राहक को अनुबंध को पढ़ने के लिए मजबूर किए बिना किए जा रहे व्यवहार का वर्णन करते हैं। बुरे नामकरण से गलत धारणाएं बन सकती हैं। में कई निर्माणकर्ताओं के लिए String, इस तार के निर्माण decoupling द्वारा हल किया जा सकता है। अंत में, ए Stringएक है String, और यह निर्माता को केवल यह स्वीकार करना चाहिए कि इसके लिए क्या आवश्यक है। अधिकांश निर्माणकर्ता रूपांतरण उद्देश्यों के लिए उजागर होते हैं, जो निर्माणकर्ताओं का दुरुपयोग है। कंस्ट्रक्टर्स को तर्क नहीं करना चाहिए , या वे जोखिम को शुरू करने में विफल रहे, आपको एक बेकार वस्तु के साथ छोड़ दिया।
विंस एमघे

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

1

init()जब आप बाहरी संसाधनों (जैसे, उदाहरण के लिए, एक नेटवर्क कनेक्शन) की जरूरत है कि वस्तुओं है काफी कुछ समझ बना सकते हैं कि समवर्ती अन्य वस्तुओं के लिए उपयोग किया जाता है। आपको ऑब्जेक्ट के जीवनकाल के लिए संसाधन को हॉग करने की आवश्यकता नहीं है / हो सकती है। ऐसी स्थितियों में, जब आप संसाधन आवंटन विफल होने की संभावना है, तो आप कंस्ट्रक्टर में संसाधन आवंटित नहीं करना चाह सकते हैं।

विशेष रूप से एम्बेडेड प्रोग्रामिंग में, आप एक नियतात्मक स्मृति पदचिह्न रखना चाहते हैं, इसलिए यह आपके रचनाकारों को जल्दी से कॉल करने के लिए आम है (अच्छा?) अभ्यास, शायद स्थिर भी, और बाद में केवल कुछ शर्तों के पूरा होने पर आरंभ करें।

ऐसे मामलों के अलावा मुझे लगता है कि सब कुछ एक निर्माता में जाना चाहिए।


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

जरुरी नहीं। आप एक ऐसी वस्तु के साथ समाप्त होते हैं जिसे आप अस्थायी रूप से सभी उद्देश्यों के लिए उपयोग नहीं कर सकते हैं। ऐसे मामलों में, ऑब्जेक्ट तब तक एक कतार या प्रॉक्सी के रूप में कार्य कर सकता है जब तक कि संसाधन उपलब्ध नहीं हो जाता। पूरी तरह से निंदा के initतरीके बहुत सीमित है, IMHO।
8

0

आम तौर पर मैं एक रचनाकार को पसंद करता हूं जो कार्यात्मक उदाहरण के लिए आवश्यक सभी तर्क प्राप्त करता है। इससे उस वस्तु की सभी निर्भरताएँ स्पष्ट हो जाती हैं।

दूसरी ओर, मैं एक साधारण कॉन्फ़िगरेशन फ्रेमवर्क का उपयोग करता हूं जिसके लिए पैरामीटर-कम सार्वजनिक निर्माता की आवश्यकता होती है, और निर्भरता और कॉन्फ़िगरेशन मानों को इंजेक्ट करने के लिए इंटरफेस। उसके बाद किया जाता है, कॉन्फ़िगरेशन ढांचा initऑब्जेक्ट की विधि को कॉल करता है : अब आपके पास मेरे लिए सभी चीजें प्राप्त हुईं, काम के लिए तैयार होने के लिए अंतिम चरण करें। लेकिन ध्यान दें: यह कॉन्फ़िगरेशन ढांचा है जो स्वचालित रूप से init विधि को कॉल करता है, जैसे कि आप इसे कॉल करना नहीं भूलेंगे।


0

कोई कोड गंध नहीं है अगर init () - विधि वस्तु के राज्य-जीवन चक्र में शब्दार्थ रूप से एम्बेडेड है।

यदि आपको वस्तु को एक सुसंगत स्थिति में रखने के लिए init () कॉल करने की आवश्यकता है तो यह एक कोड गंध है।

इस तरह की संरचना मौजूद है कई तकनीकी कारण हैं:

  1. ढाँचा हुक
  2. ऑब्जेक्ट को प्रारंभिक स्थिति में रीसेट करना (अतिरेक से बचें)
  3. परीक्षणों के दौरान ओवरराइड करने की संभावना

1
लेकिन एक सॉफ्टवेयर इंजीनियर इसे जीवन चक्र में क्यों शामिल करेगा? क्या कोई ऐसा उद्देश्य है जो न्यायोचित हो (यह विचार करके आंशिक रूप से निर्मित वस्तुओं को प्रोत्साहित करता है) और एक अधिक कुशल विकल्प द्वारा नीचे नहीं गिराया जा सकता है? मुझे लगता है कि इसे जीवन-चक्र में एम्बेड करना एक कोड गंध होगा, और यह कि इसे ऑब्जेक्ट निर्माण के बेहतर समय के साथ प्रतिस्थापित किया जाना चाहिए (यदि आप उस समय इसका उपयोग करने की योजना नहीं बनाते हैं, तो किसी ऑब्जेक्ट के लिए मेमोरी क्यों आवंटित करें? क्यों बनाएं? वह वस्तु जो आंशिक रूप से तब बनाई जाती है जब आप केवल प्रतीक्षा कर सकते हैं टिल आपको वास्तव में इसे बनाने से पहले वस्तु की आवश्यकता है?)
विंस एमघ

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

-4

नाम init कभी-कभी अपारदर्शी हो सकता है। चलो एक कार और एक इंजन लेते हैं। कार शुरू करने के लिए (केवल पावर अप, रेडियो सुनने के लिए) आप यह सत्यापित करना चाहते हैं कि सभी सिस्टम जाने के लिए तैयार हैं।

तो आप एक इंजन, एक दरवाजा, एक पहिया आदि का निर्माण करते हैं। आपकी स्क्रीन इंजन = बंद दिखाती है।

इंजन आदि की निगरानी शुरू करने की आवश्यकता नहीं है क्योंकि वे सभी महंगे हैं। फिर जब आप इंजन को आग लगाने के लिए कुंजी चालू करते हैं, तो आप शुरू करते हैं। यह सभी महंगी प्रक्रियाओं को चलाने लगता है।

अब आप इंजन = को देखें। और प्रज्वलन के लिए प्रक्रिया शुरू होती है।

इंजन उपलब्ध न होने से कार पावर नहीं करेगी।

आप इंजन को अपनी जटिल गणना से बदल सकते हैं। एक एक्सेल सेल की तरह। सभी कोशिकाओं को हर समय सभी घटना संचालकों के साथ सक्रिय होने की आवश्यकता नहीं है। जब आप एक सेल पर ध्यान केंद्रित करते हैं तो आप इसे शुरू कर सकते हैं। उस तरह से प्रदर्शन बढ़ाना।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.