एक विधि श्रृंखला के माध्यम से संदर्भ पारित करने के लिए पैटर्न


19

यह एक डिजाइन निर्णय है जो काफी हद तक सामने आता है: एक विधि के माध्यम से संदर्भ को कैसे पारित किया जाए, इसके लिए किसी विधि की आवश्यकता नहीं है। क्या कोई सही उत्तर है या क्या यह संदर्भ पर निर्भर करता है।

नमूना कोड जिसमें समाधान की आवश्यकता होती है

// needs the dependency
function baz(session) {
  session('baz');
}

// doesn't care about the dependency
function bar() {
  baz();
}

// needs the dependency
function foo(session) {
   session('foo')
   bar();
}

// creates the dependency
function start() {
  let session = new Session();
  foo(session);
}

संभव समाधान

  • threadlocal
  • वैश्विक
  • संदर्भ वस्तु
  • के माध्यम से निर्भरता पारित करें
  • करी बाज और इसे पहले आर्ग के रूप में निर्भरता सेट के साथ बार में पास करें
  • निर्भरता अन्तःक्षेपण

कहां आता है इसके उदाहरण

HTTP अनुरोध प्रसंस्करण

अनुरोध विशेषताओं के रूप में संदर्भ वस्तुएं अक्सर उपयोग की जाती हैं: एक्सप्रेसज, जावा सर्वलेट्स या .net के ओवेन देखें।

लॉगिंग

जावा लॉगिंग लोक के लिए अक्सर ग्लोबल्स / सिंगलटन का उपयोग करते हैं। ठेठ log4j / कॉमन्स लॉगिंग / जावा लॉगिंग पैटर्न देखें।

लेन-देन

थ्रेड लोकल का उपयोग अक्सर लेनदेन की प्रक्रिया से जुड़े लेन-देन या सत्र को रखने के लिए किया जाता है ताकि उन्हें उन सभी विधियों के मापदंडों के रूप में पारित करने की आवश्यकता हो, जिनकी उन्हें आवश्यकता नहीं है।


कृपया अधिक सार्थक उदाहरण का उपयोग करें।
ट्यूलेंस कोरडोवा

मैंने कुछ उदाहरण जोड़े हैं जहां यह आता है।
जेमी मैक्रिंडल ने

3
मेरा मतलब एक अधिक सार्थक उदाहरण कोड था।
ट्यूलेंस कोर्डोवा

जवाबों:


11

एकमात्र उचित उत्तर यह है कि यह आपके प्रोग्रामिंग प्रतिमान के मुहावरों पर निर्भर करता है। यदि आप OO का उपयोग कर रहे हैं, तो विधि से विधि की निर्भरता को पारित करना लगभग निश्चित रूप से गलत है। यह OO में एक कोड गंध है। वास्तव में, यह उन समस्याओं में से एक है जो OO हल करती है - एक वस्तु एक संदर्भ को ठीक करती है। तो OO में, एक सही (हमेशा अन्य तरीके होते हैं) दृष्टिकोण होता है कि निर्भरता को प्रॉपर्टी या प्रॉपर्टी के माध्यम से वितरित करना। एक टिप्पणीकार ने "निर्भरता इंजेक्शन" का उल्लेख किया है और यह पूरी तरह से वैध है, लेकिन यह कड़ाई से आवश्यक नहीं है। बस निर्भरता प्रदान करें ताकि यह एक सदस्य के रूप में उपलब्ध हो fooऔर baz

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

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


यह दावा करते हुए कि OO विधियों के भीतर पासिंग पैरामीटर एक कोड गंध है, एक अत्यधिक विवादास्पद बयान है। मैं पूर्ण विपरीत तर्क देता हूं: एक वर्ग के भीतर मिक्सिंग स्टेट और कार्यक्षमता को प्रोत्साहित करना, OO प्रतिमान द्वारा की गई सबसे बड़ी गलतियों में से एक है और सीधे तौर पर तरीकों में निर्भरता को इंजेक्ट करके इसे टालना, न कि एक कंस्ट्रक्टर के माध्यम से एक अच्छी तरह से डिज़ाइन किए गए टुकड़े का संकेत है। कोड का, ओओ या नहीं।
डेविड अरनो

3
@DavidArno मैं एक अलग प्रतिमान का उपयोग करने का सुझाव दूंगा। वस्तुस्थिति का समापन "राज्य प्रतिमान द्वारा की जाने वाली सबसे बड़ी गलतियों में से एक है" और फिर प्रतिमान को दरकिनार करना। मेरे पास लगभग किसी भी दृष्टिकोण के खिलाफ कुछ भी नहीं है, लेकिन आमतौर पर कोड को नापसंद करते हैं जहां लेखक अपने उपकरण से लड़ रहा है। निजी राज्य OO की एक विशिष्ट विशेषता है। यदि आप उस सुविधा से बचते हैं, तो आप OO की कुछ शक्ति खो देते हैं।
२१:२१ पर स्केन रोजर

1
@DavidArno एक वर्ग है जो सभी राज्य है और कोई भी कार्यक्षमता राज्य में अपरिवर्तनीय संबंधों को लागू करने के लिए कोई तंत्र नहीं है। ऐसा वर्ग ओ ओ में नहीं है।
केविन क्रुमविडे

@KevinKrumwiede, एक हद तक, आपने मेरी टिप्पणी पर reducto ad absudium लागू किया है, लेकिन आपकी बात अभी भी अच्छी तरह से बनी हुई है। राज्य पर आक्रमण "ओओ से आगे बढ़ना" का एक महत्वपूर्ण हिस्सा है। इसलिए मिक्सिंग फंक्शनालिटी और स्टेट से बचना पड़ता है क्योंकि अचीव करने के लिए स्टेट ऑब्जेक्ट में पर्याप्त फंक्शनैलिटी होती है।
डेविड अरनो

@ScantRoger, मैं मानता हूं कि एक और प्रतिमान अपनाया जा सकता है, अर्थात् कार्यात्मक प्रतिमान। दिलचस्प है, अधिकांश आधुनिक "ओओ" भाषाओं में कार्यात्मक सुविधाओं की बढ़ती सूची है और इसलिए "टूल से लड़ने के बिना" उन भाषाओं के साथ चिपकना और फ़ंक्शन प्रतिमान को अपनाना संभव है।
डेविड अरनो

10

यदि barनिर्भर है baz, जो बदले में आवश्यकता होती है dependency, तो सही ढंग से उपयोग करने के लिए भी barआवश्यकता होती dependencyहै baz। इसलिए, सही दृष्टिकोण या तो निर्भरता पास करने के लिए एक पैरामीटर के रूप में barया करी bazऔर पास करने के लिए होगा bar

पहला दृष्टिकोण लागू करने और पढ़ने के लिए सरल है, लेकिन barऔर के बीच एक युग्मन बनाता है baz। दूसरा दृष्टिकोण उस युग्मन को हटा देता है, लेकिन परिणाम कम स्पष्ट हो सकता है। इसलिए जो दृष्टिकोण सबसे अच्छा है, वह संभवतः दोनों कार्यों की जटिलता और व्यवहार पर निर्भर करेगा। उदाहरण के लिए, यदि साइड इफेक्ट्स bazया dependencyदुष्प्रभाव हैं, तो आसानी से परीक्षण एक बड़ा ड्राइवर होगा जिसमें समाधान चुना जाता है।

मैं सुझाव देता हूं कि आपके द्वारा प्रस्तावित अन्य सभी विकल्प प्रकृति में "हैकी" दोनों हैं और परीक्षण के साथ और बग को ट्रैक करने के लिए मुश्किल दोनों समस्याओं का नेतृत्व करने की संभावना है।


1
मैं लगभग पूरी तरह से सहमत हूं। निर्भरता इंजेक्शन एक और गैर- "हैकी" aproach हो सकता है।
जोनाथन वैन डे वीन

1
@JonathanvandeVeen, निश्चित रूप dependencyसे मापदंडों के माध्यम से चारों ओर से गुजरने का बहुत निर्भरता इंजेक्शन है?
डेविड अरनो

2
@DavidArno निर्भरता इंजेक्शन ढांचे को इस प्रकार की निर्भरता से छुटकारा नहीं मिलता है, वे बस उन्हें स्थानांतरित करते हैं। जादू यह है कि वे उन्हें आपकी कक्षाओं के बाहर स्थानांतरित कर देते हैं, ऐसी जगह जहां परीक्षण करना कोई समस्या है।
केविन क्रुमविडे ने

@JonathanvandeVeen मैं सहमत हूं, निर्भरता इंजेक्शन एक वैध समाधान है। वास्तव में यह वह है जिसे मैं अक्सर चुनता हूँ।
जेमी मैक्रिंडल 16

1

दार्शनिक रूप से बोलना

मैं डेविड अरनो की चिंता से सहमत हूं ।

मैं कार्यान्वयन समाधानों की तलाश में ओपी पढ़ रहा हूं। हालांकि, जवाब डिजाइन बदल रहा है । "पैटर्न"? OO डिजाइन है, एक संदर्भ के बारे में सब कह सकता है। यह संभावनाओं के साथ गर्भवती गर्भवती कागज की एक विशाल, खाली शीट है।

मौजूदा कोड से निपटना एक अलग, अच्छी तरह से, संदर्भ है।



मैं अभी 'समान रूप से एक ही समस्या पर काम कर रहा हूँ। ठीक है, मैं कोड कॉपी-एन-पेस्ट की सैकड़ों लाइनें तय कर रहा हूं जो कि किया गया था ताकि एक मूल्य इंजेक्ट किया जा सके।

कोड को संशोधित करें

मैंने डुप्लिकेट कोड की 600 लाइनों को फेंक दिया, फिर "ए कॉल्स बी कॉल सी कॉल डी ..." के बजाय "कॉल ए, रिटर्न, कॉल बी, रिटर्न, कॉल सी ..." को हटा दिया। अब हमें केवल उन तरीकों में से एक में मूल्य इंजेक्ट करने की आवश्यकता है, चलो विधि ई कहते हैं।

कंस्ट्रक्टर में एक डिफ़ॉल्ट पैरामीटर जोड़ें। मौजूदा कॉलर्स नहीं बदलते हैं - "वैकल्पिक" यहां ऑपरेटिव शब्द है। यदि कोई तर्क पारित नहीं होता है तो डिफ़ॉल्ट मान का उपयोग किया जाता है। तब केवल 1 लाइन परिवर्तन को वैरिएबल, मॉड्यूलर संरचना में चर को पारित करने के लिए; और इसका उपयोग करने के लिए विधि E में एक छोटा सा बदलाव।


बंद

एक प्रोग्रामर धागा - "एक कार्यक्रम एक बंद का उपयोग क्यों करेगा?"

अनिवार्य रूप से, आप मूल्यों को एक विधि में इंजेक्ट कर रहे हैं जो मानों के साथ अनुकूलित एक विधि लौटाता है। उस अनुकूलित विधि को बाद में निष्पादित किया जाता है।

यह तकनीक आपको अपना हस्ताक्षर बदले बिना किसी मौजूदा पद्धति को संशोधित करने की अनुमति देगी।


यह दृष्टिकोण विचित्र रूप से परिचित लगता है ...

लौकिक युग्मन (आपके लिंक) मुद्दे पर रोजर, @ सस्मान। यह महत्वपूर्ण है कि आवश्यक निष्पादन आदेश को संक्षिप्त कर दिया जाए।
राडारबॉब
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.