पैरामीटर सूची में लकड़हारा की स्थिति क्या होनी चाहिए [बंद]


12

अपने कोड में मैं अपने निर्माता की पैरामीटर सूची के माध्यम से अपने कई वर्गों के लिए एक लकड़हारा इंजेक्ट करता हूं

मैंने देखा कि मैंने इसे यादृच्छिक रूप से रखा: कभी-कभी यह सूची में पहला, कभी-कभी अंतिम और कभी-कभी बीच में होता है

क्या आपकी कोई प्राथमिकता है? मेरा अंतर्ज्ञान कहता है कि इस मामले में स्थिरता मददगार है और मेरी व्यक्तिगत प्राथमिकता है कि इसे पहले रखा जाए, इसलिए जब इसे याद किया जाता है तो इसे देखा जाना आसान होता है और जब यह वहां होता है तो इसे छोड़ना आसान होता है।

जवाबों:


30

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

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

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

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


11
+! निर्माता लकड़ियों से लकड़हारा बाहर रखें; मैं एक स्थिर लकड़हारा पसंद करता हूं, इसलिए मुझे पता है कि हर कोई एक ही चीज का उपयोग कर रहा है
स्टीवन ए। लोव

1
@ StevenA.Lowe ध्यान दें कि अगर स्टैटिक लॉगर का उपयोग करने से लाइन में अन्य समस्याएं हो सकती हैं यदि आप सावधान नहीं हैं (उदाहरण के लिए। C पर ++ में स्थिर इनिशियलाइज़ेशन ऑर्डर फ़ाइस्को)। मैं इस बात से सहमत हूं कि वैश्विक स्तर पर सुलभ इकाई के रूप में लकड़हारे के पास इसके आकर्षण हैं, लेकिन इस बात का सावधानीपूर्वक मूल्यांकन किया जाना चाहिए कि इस तरह का डिजाइन समग्र वास्तुकला में फिट बैठता है या नहीं।
कॉमिकसंस

@ComicSansMS: बेशक, प्लस थ्रेडिंग मुद्दों आदि बस एक व्यक्तिगत प्राथमिकता - "जितना संभव हो उतना सरल, लेकिन सरल";)
स्टीवन ए। लोव

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

@ श्लोत्रियो: यह एक स्थिर लकड़हारे की सुंदरता है। किसी भी तरह के इंजेक्शन की आवश्यकता नहीं है।
रॉबर्ट हार्वे

7

फ़ंक्शन ओवरलोडिंग वाली भाषाओं में, मैं तर्क दूंगा कि वैकल्पिक होने की संभावना जितनी अधिक होगी, उतना ही अधिक सही होना चाहिए। जब आप ओवरलोड्स बनाते हैं, जहां वे गायब होते हैं, तो यह संगतता बनाता है:

foo(mandatory);
foo(mandatory, optional);
foo(mandatory, optional, evenMoreOptional);

कार्यात्मक भाषाओं में रिवर्स अधिक उपयोगी है - जितना अधिक आप कुछ डिफ़ॉल्ट चुनने की संभावना रखते हैं, उतना ही आगे छोड़ दिया जाना चाहिए। इससे केवल तर्कों को लागू करके फ़ंक्शन को विशेषज्ञ बनाना आसान हो जाता है:

addThreeToList = map (+3)

हालाँकि जैसा कि अन्य उत्तरों में बताया गया है, आप शायद सिस्टम के हर वर्ग के तर्क सूची में लकड़हारे को स्पष्ट रूप से पास नहीं करना चाहते हैं।


3

आप निश्चित रूप से इस समस्या को खत्म करने में बहुत अधिक समय लगा सकते हैं।

कैनोनिकल लॉगिंग कार्यान्वयन के साथ भाषाओं के लिए, बस हर वर्ग में सीधे कैनोनिकल लॉगर को तत्काल करें।

विहित कार्यान्वयन के बिना भाषाओं के लिए, एक लॉगिंग मुखौटा ढांचा खोजने की कोशिश करें और उससे चिपके रहें। slf4j जावा में एक अच्छा विकल्प है।

व्यक्तिगत रूप से मैं बल्कि एक ही ठोस लॉगिंग कार्यान्वयन के लिए छड़ी और सब कुछ syslog को भेजना होगा। सभी अच्छे लॉग विश्लेषण उपकरण कई ऐप सर्वर से एक विस्तृत रिपोर्ट में sysout लॉग को संयोजित करने में सक्षम हैं।

जब एक फ़ंक्शन हस्ताक्षर में एक या दो निर्भरता सेवाएं और साथ ही कुछ "वास्तविक" तर्क शामिल होते हैं, तो मैं निर्भरता को अंतिम स्थान देता हूं:

int calculateFooBarSum(int foo, int bar, IntegerSummationService svc)

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

यदि आप अपने आप को अपने ऐप में एक दर्जन से अधिक या निर्भरता का इंजेक्शन लगाते हैं, तो सिस्टम को संभवतः अलग-अलग सबसिस्टम में विभाजित करने की आवश्यकता है (मैं माइक्रोसर्विस कहूं?)।


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

2

लकड़हारे एक विशेष मामले के एक बिट हैं क्योंकि उन्हें हर जगह शाब्दिक रूप से उपलब्ध होना है।

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

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


1

मैं उन लोगों से सहमत हूं जो यह तर्क देते हैं कि लकड़हारा को कक्षाओं में पारित होने के बजाय सांख्यिकीय रूप से एक्सेस किया जाना चाहिए। हालाँकि अगर कोई मजबूत कारण है जिसे आप इसे पास करना चाहते हैं (शायद अलग-अलग उदाहरण अलग-अलग स्थानों या किसी चीज़ पर लॉग इन करना चाहते हैं) तो मैं आपको सुझाव दूंगा कि आप इसे कंस्ट्रक्टर का उपयोग करके पास न करें, Class* C = new C(); C->SetLogger(logger);बल्कि ऐसा करने के लिए एक अलग कॉल करें, जैसे कि सेClass* C = new C(logger);

इस पद्धति को पसंद करने का कारण यह है कि लकड़हारा अनिवार्य रूप से कक्षा का हिस्सा नहीं है, बल्कि किसी अन्य उद्देश्य के लिए इस्तेमाल किया जाने वाला इंजेक्शन है। इसे निर्माणकर्ता सूची में रखने से यह कक्षा की आवश्यकता बन जाती है और इसका अर्थ है कि यह कक्षा की वास्तविक तार्किक स्थिति का हिस्सा है। यह उम्मीद करना, उचित है (उदाहरण के लिए, हालांकि सारे अधिकांश वर्गों के साथ), कि अगर X != Yउसके बाद C(X) != C(Y), लेकिन यह संभावना नहीं है कि आप लकड़हारा असमानता का परीक्षण होगा यदि आप भी एक ही कक्षा के उदाहरण की तुलना कर रहे है।


1
बेशक इसका दोष यह है कि लकड़हारा निर्माणकर्ता के लिए अनुपलब्ध है।
बेन वोइगट

1
मुझे वास्तव में यह उत्तर पसंद है। यह लॉगिंग को उस वर्ग की चिंता का विषय बनाता है जिसका आपको केवल उपयोग करने से अलग से ध्यान रखना है। संभावना है कि यदि आप बड़ी संख्या में वर्गों के निर्माता को लकड़हारा जोड़ रहे हैं, तो आप शायद निर्भरता इंजेक्शन का उपयोग कर रहे हैं। मैं सभी भाषाओं के लिए बात नहीं कर सकता, लेकिन मैं C # में जानता हूं, कुछ DI कार्यान्वयन सीधे संपत्तियों (गेट्टर / सेटर) को भी इंजेक्ट करेंगे ।
jpmc26

@BenVoigt: यह सच है, और यह इस तरह से नहीं करने के लिए एक हत्यारा कारण हो सकता है लेकिन, आमतौर पर, आप लॉग ऑन किए जाने के जवाब में कंस्ट्रक्टर में लॉगिंग कर सकते हैं अन्यथा आप कर सकते हैं।
जैक एडले

0

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

स्टेटिक खुद को उसी मुद्दे पर उधार देता है; यदि लकड़हारा काम नहीं करता है, तो आपकी पूरी कक्षा विफल हो जाती है (यदि आपकी कक्षा लकड़हारे का उपयोग करती है) - भले ही लकड़हारा आवश्यक रूप से वर्ग की जिम्मेदारी का 'हिस्सा' न हो - हालांकि यह संपत्ति इंजेक्शन के रूप में लगभग उतना बुरा नहीं है क्योंकि आप कम से कम जानते हैं कि लकड़हारा हमेशा एक अर्थ में "वहाँ" होता है।

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


1
हम्म् ... तो आप चाहते हैं कि आपकी कक्षा लॉगिंग का प्रदर्शन करे (लॉगिंग विनिर्देश में होनी चाहिए) लेकिन आप लकड़हारे का उपयोग करके परीक्षण नहीं करना चाहते हैं। क्या यह संभव है? मुझे लगता है कि आपकी बात एक गैर है। स्पष्ट रूप से अगर आपके परीक्षण उपकरण टूट गए हैं तो आप परीक्षण नहीं कर सकते हैं - परीक्षण उपकरण पर भरोसा नहीं करने के लिए एक तरह से डिजाइन करने के लिए ओवर-इंजीनियरिंग IMHO का एक सा है
होगन

1
मेरा कहना यह है कि अगर मैं एक कंस्ट्रक्टर का उपयोग करता हूं और एक विधि को एक वर्ग पर कॉल करता हूं और यह अभी भी विफल रहता है क्योंकि मैंने कोई संपत्ति निर्धारित नहीं की है, तो क्लास के डिजाइनर ने एक कंस्ट्रक्टर के पीछे की अवधारणा को गलत समझा है। यदि एक लकड़हारा को कक्षा की आवश्यकता होती है, तो उसे निर्माता में इंजेक्ट किया जाना चाहिए - यही वह है जो निर्माणकर्ता के लिए है।
दान पेंट्री

उम्म .. नहीं सच में नहीं। यदि आप लॉगिंग सिस्टम को "फ्रेमवर्क" का हिस्सा मानते हैं तो इसका मतलब कंस्ट्रक्टर के हिस्से से कोई मतलब नहीं है। लेकिन यह अन्य उत्तरों में स्पष्ट रूप से कहा गया है।
होगन

1
मैं प्रॉपर्टी इंजेक्शन के खिलाफ बहस कर रहा हूं। मैं जरूरी नहीं कि इसे कंस्ट्रक्टर में इंजेक्ट करने के लिए वकालत कर रहा हूं। मैं सिर्फ यह कह रहा हूं कि मेरी राय में, यह संपत्ति इंजेक्शन के लिए बेहतर है।
डैन पेंट्री

"क्या यह संभव है?" यह भी, हाँ, आईएल बुनाई एक ऐसी चीज है जो मौजूद है और शीर्ष उत्तर में उल्लेख किया गया था ... मोनो-project.com/docs/tools+lbooks/lbooks/Mono.Cecil
Dan Pantry

0

मैं प्रत्येक वर्ग उदाहरण के लिए एक लकड़हारे वस्तु के आसपास से गुजरने में बहुत आलसी हूँ। तो, मेरे कोड में, इस प्रकार की चीजें या तो स्थिर क्षेत्र में बैठती हैं या स्थिर क्षेत्र में थ्रेड-लोकल वैरिएबल। उत्तरार्द्ध शांत प्रकार का है और आपको प्रत्येक थ्रेड के लिए एक अलग लकड़हारा उपयोग करने देता है और आपको बहु-थ्रेडेड एप्लिकेशन में सार्थक और अपेक्षित कुछ करने के लिए लॉगिंग को चालू और बंद करने की विधियाँ जोड़ने देता है।

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