तथाकथित "क्रॉस-कटिंग चिंताओं" को SOLID / DI / IoC तोड़ने का एक वैध बहाना कहा जाता है?


43

मेरे सहयोगियों को "लॉगिंग / कैशिंग / आदि कहना पसंद है। यह एक क्रॉस-कटिंग चिंता है" और फिर हर जगह इसी सिंगलटन का उपयोग करके आगे बढ़ें। फिर भी वे IoC और DI से प्यार करते हैं।

क्या यह वास्तव में एसओएलआई डी सिद्धांत को तोड़ने के लिए एक वैध बहाना है ?


27
मैंने पाया है कि SOLID सिद्धांत ज्यादातर उन लोगों के लिए ही उपयोगी होते हैं, जिनके पास पहले से ही अनजाने में आवश्यक अनुभव होता है।
svidgen

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

4
@svidgen SOLID सिद्धांत भी उपयोगी हैं, जब वे नहीं जानते जो उन्हें आपके कोड की समीक्षा करते हैं और आपसे पूछते हैं कि आपने ऐसा क्यों किया। यह एक सिद्धांत पर इंगित करने और "यही कारण है" कहने में सक्षम होने के लिए अच्छा है
कैंडिड_ऑरेंज

1
क्या आपके पास कोई उदाहरण है जो आपको लगता है कि लॉगिंग एक विशेष मामला है? यह कुछ डेटा को पुनर्निर्देशित करने के लिए काफी सरलीकृत चैनल है, आमतौर पर जो भी एक्स फ्रेमवर्क आप उपयोग कर रहे हैं उसका हिस्सा है।
ksiimson

जवाबों:


42

नहीं।

अपरिहार्य परिवर्तन के लिए दिशानिर्देश के रूप में SOLID मौजूद है। क्या आप वास्तव में अपनी लॉगिंग लाइब्रेरी, या लक्ष्य, या फ़िल्टरिंग, या स्वरूपण, या ... को बदलने के लिए कभी नहीं जा रहे हैं? क्या आप वास्तव में अपनी कैशिंग लाइब्रेरी, या लक्ष्य, या रणनीति, या स्कूपिंग, या ... को बदलने नहीं जा रहे हैं?

बेशक आप ही हैं। पर बहुत कम से कम , आप एक समझदार तरह से इन बातों को उपहास करने के लिए परीक्षण के लिए उन्हें अलग करने के लिए चाहते करने जा रहे हैं। और अगर आप उन्हें परीक्षण के लिए अलग करना चाहते हैं, तो आप संभवतः एक व्यावसायिक कारण में भाग लेने जा रहे हैं जहाँ आप उन्हें जीवन के अन्य कारणों से अलग करना चाहते हैं।

और फिर आपको तर्क मिलेगा कि लकड़हारा खुद बदलाव को संभाल लेगा। "ओह, अगर लक्ष्य / फ़िल्टरिंग / स्वरूपण / रणनीति में बदलाव होता है, तो हम बस कॉन्फ़िगरेशन बदल देंगे!" वह कचरा है। इतना ही नहीं अब आपके पास एक ईश्वर वस्तु है जो इन सभी चीजों को संभालती है, आप अपना कोड XML (या समान) में लिख रहे हैं जहाँ आपको स्थैतिक विश्लेषण नहीं मिलता है, आपको संकलन समय त्रुटियाँ नहीं मिलती हैं, और आप डॉन ' टी वास्तव में प्रभावी इकाई परीक्षण प्राप्त करते हैं।

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

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


22
फिर आपके पास क्या विकल्प है? आप लिख रहे हर वर्ग में एक ILogger इंजेक्षन? हर वर्ग के लिए डेकोरेटर लिखना जो लकड़हारे की जरूरत है?
रॉबर्ट हार्वे

16
हाँ। अगर कुछ निर्भरता है, तो यह एक निर्भरता है । और अगर इसका मतलब बहुत अधिक निर्भरताएं हैं, या आप एक लकड़हारा पास कर रहे हैं तो यह कहीं नहीं जाना चाहिए - अच्छा , अब आप अपने डिजाइन को ठीक कर सकते हैं।
तेलस्तीन


20
वास्तविक मुद्दा मेरे पास dogmatic IoC के साथ है, जो कि सभी आधुनिक कोड बहुत कुछ पर निर्भर करता है जो न तो इंजेक्ट किया जाता है और न ही दूर होता है। आप लिखते हैं सी #, उदाहरण के लिए, आप नहीं अक्सर सार करने के लिए जा रहे हैं Stringया Int32यहां तक कि या Listअपने मॉड्यूल से बाहर। इसमें कुछ हद तक बदलाव की योजना के लिए उचित और समझदार है। और, ज्यादातर स्पष्ट "कोर" प्रकारों से परे, समझदारी से कि आप जो बदलाव कर सकते हैं वह वास्तव में अनुभव और निर्णय का मामला है।
svidgen

6
@ एसवीडजेन - मुझे उम्मीद है कि आपने मेरे उत्तर को हठधर्मी आईओसी की वकालत के रूप में नहीं पढ़ा होगा। और सिर्फ इसलिए कि हम इन मूल प्रकारों (और अन्य चीजें जहां विवेकपूर्ण नहीं हैं) को अलग नहीं करते हैं, इसका मतलब यह नहीं है कि वैश्विक सूची / स्ट्रिंग / इंट / आदि होना ठीक है।
तेलस्तीन

38

हाँ

यह "क्रॉस-कटिंग चिंता" शब्द का पूरा बिंदु है - इसका मतलब है कि कुछ ऐसा है जो SOLID सिद्धांत में बड़े करीने से फिट नहीं होता है।

यह वह जगह है जहाँ आदर्शवाद वास्तविकता के साथ मिलता है।

SOLID में नए लोग और क्रॉस-कटिंग अक्सर इस मानसिक चुनौती में दौड़ते हैं। यह ठीक है, बाहर बेकार नहीं है। सब कुछ SOLID के संदर्भ में रखने के लिए प्रयास करें, लेकिन लॉगिंग और कैशिंग जैसे कुछ स्थान हैं जहां SOLID का कोई मतलब नहीं है। क्रॉस-कटिंग SOLID का भाई है, वे हाथ से चलते हैं।


9
एक तर्कपूर्ण, व्यावहारिक, गैर-हठधर्मी जवाब।
user1936

11
क्या आप हमें बता सकते हैं कि क्रॉस-कटिंग चिंताओं से सभी पांच ठोस सिद्धांत क्यों टूट गए? मुझे यह समझने में समस्या है।
डॉक ब्राउन

4
हाँ। मैं संभावित रूप से प्रत्येक सिद्धांत को व्यक्तिगत रूप से "तोड़ने" के लिए एक अच्छा कारण सोच सकता था; लेकिन सभी 5 को तोड़ने का एक भी कारण नहीं!
svidgen

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

2
@Dvnull शायद यह मुद्दा तब है, बजाय खुद को काटने की चिंताओं के ...
बोरिस स्पाइडर

25

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

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

मुझे लगता है कि कैशिंग एक पूरी तरह से अलग परिदृश्य है, हालांकि।


3
अब तक एफपी में थोड़ा डब होने के बाद, मैं अपने उपयोग के मामलों में मुख्य व्यवसाय तर्क () में कोई भी डाले बिना लॉगिंग, त्रुटि हैंडलिंग आदि जैसे सामान (शायद मोनैडिक) का उपयोग करने में एक बड़ी रुचि विकसित करने के लिए आया हूं। देखें fsharpforfunandprofit.com/rop )
सारा

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

12
@RubberDuck - मुझे बताएं कि "लॉगिंग को व्यापक नहीं होना चाहिए" जब मुझे फ़ील्ड से बग रिपोर्ट मिलती है और एकमात्र डिबग क्षमता मुझे यह पता लगाने की होती है कि क्या हुआ है तो वह लॉग फ़ाइल जिसे मैं व्यापक बनाना नहीं चाहता था। सबक सीखा, लॉगिंग "व्यापक" होना चाहिए, बहुत व्यापक।
डंक

15
@ रबरडक: सर्वर सॉफ्टवेयर के साथ, लॉगजीआई जीवित रहने का एकमात्र तरीका है। यह एक बग का पता लगाने का एकमात्र तरीका है जो आपके लैपटॉप पर अभी के बजाय 12 घंटे पहले हुआ था। शोर के बारे में चिंता मत करो। लॉग प्रबंधन सॉफ्टवेयर का उपयोग करें ताकि आप अपने लॉग को क्वेरी कर सकें (आदर्श रूप से आपको अलार्म भी सेट करना चाहिए जो आपको त्रुटि लॉग पर ईमेल करेगा)
स्लीवेटमैन

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

12

मेरे 2 सेंट ...

हां और ना।

आप कभी नहीं करना चाहिए वास्तव में सिद्धांतों आप को अपनाने का उल्लंघन; लेकिन, आपके सिद्धांतों को हमेशा उच्च स्तर तक सेवा में अपनाया और अपनाया जाना चाहिए। इसलिए, ठीक से समझ में आने के साथ, कुछ स्पष्ट उल्लंघन "भावना" या "सिद्धांतों के शरीर के रूप में वास्तविक उल्लंघन नहीं हो सकते हैं ।"

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

तो, क्या SOLID में D के बारे में ? ठीक है, यह आपके पुन: प्रयोज्य मॉड्यूल को इसके संदर्भ में अपेक्षाकृत अज्ञेय बनाकर निरंतरता बढ़ाने में योगदान देता है। और हम "पुन: प्रयोज्य मॉड्यूल" को "किसी अन्य विशिष्ट संदर्भ में उपयोग किए जाने वाले कोड की एक संग्रह" के रूप में परिभाषित कर सकते हैं। और यह एक ही कार्य, वर्गों, कक्षाओं के सेट और कार्यक्रमों पर लागू होता है।

और हां, लकड़हारा कार्यान्वयन को बदलना संभवतः आपके मॉड्यूल को "एक और अलग संदर्भ" में डाल देता है।

तो, मुझे अपने दो बड़े कैवेट की पेशकश करें :

सबसे पहले: "पुन: प्रयोज्य मॉड्यूल" बनाने वाले कोड के ब्लॉकों के आसपास की रेखाओं को खींचना पेशेवर निर्णय का विषय है। और आपका निर्णय आवश्यक रूप से आपके अनुभव तक सीमित है।

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

यदि आप निर्णय में अपनी त्रुटियों के बारे में दोषी महसूस करते हैं, तो स्वीकारोक्ति पर जाएं और आगे बढ़ें ...

दूसरी बात: इनवर्टिंग नियंत्रण निर्भरता निर्भर करने के बराबर नहीं है ।

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

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

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

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


4
यार ... मैं एक छोटा सा जवाब दिया होता, लेकिन मेरे पास समय नहीं था।
13:30 बजे svidgen

2
एडेप्टर का उपयोग करने के लिए +1। आपको 3-पार्टी घटकों पर निर्भरता को अलग करने की आवश्यकता है ताकि उन्हें जहां भी संभव हो प्रतिस्थापित किया जा सके। लॉगिंग इसके लिए एक आसान लक्ष्य है - कई लॉगिंग कार्यान्वयन मौजूद हैं और ज्यादातर समान API हैं, इसलिए एक साधारण एडाप्टर कार्यान्वयन आपको उन्हें बहुत आसानी से बदलने की अनुमति दे सकता है। और जो लोग कहते हैं कि आप अपने लॉगिंग प्रदाता को कभी नहीं बदलेंगे: मुझे ऐसा करना पड़ा है, और यह एक वास्तविक दर्द का कारण बना क्योंकि मैं एक एडाप्टर का उपयोग नहीं कर रहा था।
जूल्स

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

जब भी मैं किसी पुराने उत्तर पर +1 या टिप्पणी देखता हूं, मैं अपने उत्तर को फिर से पढ़ता हूं और फिर से खोजता हूं, कि मैं एक बहुत ही अव्यवस्थित और अस्पष्ट लेखक हूं ... मैं टिप्पणी की सराहना करता हूं, हालांकि, @dvk।
svidgen

एडेप्टर जीवन रक्षक होते हैं, वे ज्यादा खर्च नहीं करते हैं और आपके जीवन को बहुत आसान बनाते हैं, विशेषकर जब आप SOLID लागू करना चाहते हैं। परीक्षण उनके साथ एक हवा है।
एलन

8

यह विचार कि लॉगिंग को हमेशा एक सिंगलटन के रूप में लागू किया जाना चाहिए , उन झूठों में से एक है जिन्हें अक्सर कहा गया है कि यह कर्षण प्राप्त कर चुका है।

जब तक आधुनिक ऑपरेटिंग सिस्टम के बारे में यह माना जाता है कि आप आउटपुट की प्रकृति के आधार पर कई स्थानों पर लॉग इन करना चाहते हैं ।

सिस्टम डिज़ाइनरों को लगातार नए समाधानों में नेत्रहीन रूप से उन्हें शामिल करने से पहले अतीत की प्रभावकारिता पर सवाल उठाना चाहिए। अगर वे ऐसा परिश्रम नहीं कर रहे हैं, तो वे अपना काम नहीं कर रहे हैं।


2
आपका प्रस्तावित समाधान क्या है? क्या यह आपके द्वारा लिखे गए प्रत्येक वर्ग में ILogger को इंजेक्ट कर रहा है? डेकोरेटर पैटर्न का उपयोग करने के बारे में क्या?
रॉबर्ट हार्वे

4
वास्तव में मेरे सवाल का जवाब नहीं, क्या यह है? मैंने केवल उदाहरणों के रूप में पैटर्न को कहा है ... यदि आपके मन में कुछ बेहतर है तो यह होना जरूरी नहीं है।
रॉबर्ट हार्वे

8
मैं वास्तव में किसी ठोस प्रस्ताव के संदर्भ में इस उत्तर को नहीं समझता
ब्रायन एग्न्यू

3
@ रॉबीडी - तो आप कह रहे हैं कि लॉगिंग को "बंद-मौका" द्वारा सबसे जटिल और असुविधाजनक तरीके से लागू किया जाना चाहिए जिसे हम कई स्थानों पर लॉग इन करना चाहते हैं? यहां तक ​​कि अगर ऐसा परिवर्तन हुआ है, तो क्या आपको लगता है कि मौजूदा लकड़हारा उदाहरण के लिए कार्यक्षमता को जोड़ना सभी वर्गों से उस लकड़हारे को पारित करने के लिए सभी प्रयासों की तुलना में अधिक काम करने वाला है, जब आप तय करते हैं कि आप एक लकड़हारा चाहते हैं या नहीं। दर्जनों परियोजनाएं जहां कई जगह लॉगिंग कभी नहीं होगी?
डंक

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

4

वास्तव में लॉगिंग एक विशेष मामला है।

@ टेलस्टीन लिखते हैं:

क्या आप वास्तव में अपनी लॉगिंग लाइब्रेरी, या लक्ष्य, या फ़िल्टरिंग, या स्वरूपण, या ... को बदलने के लिए कभी नहीं जा रहे हैं?

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

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

संक्षेप में, ये समस्याएँ हैं ... लॉगिंग के लिए ... और इसलिए इन्हें हल करने के लिए डिपेंडेंसी इंजेक्शन का उपयोग करने की आवश्यकता नहीं है।

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

@ टेलस्टीन लिखते हैं:

और फिर आपको तर्क मिलेगा कि लकड़हारा खुद बदलाव को संभाल लेगा। "ओह, अगर लक्ष्य / फ़िल्टरिंग / स्वरूपण / रणनीति में बदलाव होता है, तो हम बस कॉन्फ़िगरेशन बदल देंगे!" वह कचरा है। इतना ही नहीं अब आपके पास एक ईश्वर वस्तु है जो इन सभी चीजों को संभालती है, आप अपना कोड XML (या समान) में लिख रहे हैं जहाँ आपको स्थैतिक विश्लेषण नहीं मिलता है, आपको संकलन समय त्रुटियाँ नहीं मिलती हैं, और आप डॉन ' टी वास्तव में प्रभावी इकाई परीक्षण प्राप्त करते हैं।

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

ज़रूर, अगर आप लॉगिंग कॉन्फिग्स को स्टफ करते हैं तो आपको समस्याएँ हो सकती हैं, लेकिन वे स्टार्टअप के दौरान या तो एप्लिकेशन फेल होने या बहुत अधिक / बहुत कम लॉगिंग के रूप में प्रकट होंगे। 1) इन समस्याओं को विन्यास फाइल में गलती को ठीक करके आसानी से तय किया जाता है। 2) विकल्प हर बार जब आप लॉगिंग स्तरों में बदलाव करते हैं तो एक पूर्ण निर्माण / विश्लेषण / परीक्षण / तैनाती चक्र होता है। यह स्वीकार्य नहीं है।


3

हाँ और नहीं !

हां: मुझे लगता है कि यह उचित है कि विभिन्न सबसिस्टम (या सिमेंटिक लेयर्स या लाइब्रेरीज़ या मॉड्यूलर बंडलिंग की अन्य धारणाएँ) प्रत्येक सबसिस्टम (समान या समान) को एक समान सामान्य एकलिंगलोन पर निर्भर करने वाले सभी सबसिस्टमों के बजाय उनके इनिशियलाइज़ेशन के दौरान स्वीकार करते हैं ।

हालाँकि,

नहीं: यह हर छोटी वस्तु (कंस्ट्रक्टर या इंस्टेंस विधि द्वारा) में लॉगिंग को पैरामीटर करने के लिए अनुचित है। अनावश्यक और व्यर्थ ब्लोट से बचने के लिए, छोटी संस्थाओं को अपने संलग्न संदर्भ के सिंगलटन लॉगर का उपयोग करना चाहिए।


यह कई अन्य लोगों के बीच स्तरों में प्रतिरूपकता के बारे में सोचने का एक कारण है: तरीकों को कक्षाओं में बांधा जाता है, जबकि कक्षाओं को उप-प्रणालियों और / या अर्थ परतों में बांधा जाता है। ये बड़े बंडल अमूर्तन के मूल्यवान उपकरण हैं; हमें उन्हें पार करते समय मॉड्यूलर सीमाओं के भीतर अलग-अलग विचार देना चाहिए।


3

सबसे पहले यह मजबूत सिंगलटन कैश के साथ शुरू होता है, आपके द्वारा देखी जाने वाली अगली चीजें डेटाबेस परत के लिए मजबूत सिंगलटन हैं जो वैश्विक स्थिति, गैर-वर्णनात्मक एपीआई के classएसई और अनस्टेबल कोड की शुरुआत करती हैं।

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

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

पिछले एक दशक में मैंने प्रोग्रामिंग में खर्च किया है, केवल एक ही मामला था जहां मुझे लॉगिंग लॉजिक (जो तब सिंगलटन के रूप में लिखा गया था) को बदलने का प्रयास देखा गया। इसलिए यद्यपि मुझे निर्भरता के इंजेक्शन पसंद हैं, फिर भी लॉगिंग वास्तव में इतनी बड़ी चिंता नहीं है। दूसरी ओर, कैश, मैं निश्चित रूप से हमेशा एक निर्भरता के रूप में बनाऊंगा।


हां, लॉगिंग शायद ही कभी बदलती है और आमतौर पर एक स्वैपेबल मॉड्यूल नहीं होता है। हालांकि, मैंने एक बार एक लॉगिंग हेल्पर क्लास की इकाई-परीक्षण करने की कोशिश की, जिसमें लॉगिंग सिस्टम पर एक स्थिर निर्भरता थी। मैंने यह तय करने के लिए सबसे आसान तंत्र का परीक्षण किया कि यह एक अलग प्रक्रिया में परीक्षण के तहत कक्षा को चलाने के लिए होगा, STDOUT को लिखने के लिए इसके लकड़हारे को कॉन्फ़िगर करें, और अपने परीक्षण के मामले में उस आउटपुट को पार्स करें ಠ_ಠ मुझे घड़ियों के साथ ऐसा ही अनुभव हुआ है जहां आप ' d स्पष्ट रूप से वास्तविक समय के अलावा कभी भी कुछ नहीं चाहिए? जब, समय क्षेत्र / डीएसटी बढ़त मामलों का परीक्षण निश्चित रूप से छोड़कर ...
आमोन

@amon: घड़ियाँ लॉगिंग की तरह होती हैं, जिसमें पहले से ही एक और तंत्र होता है जो DI, जोडा-टाइम और इसके कई पोर्ट के समान उद्देश्य को पूरा करता है। (ऐसा नहीं है कि इसके बजाय डि का उपयोग करने के साथ कुछ भी गलत है; लेकिन कस्टम इंजेक्टेबल एडेप्टर लिखने की कोशिश करने की तुलना में सीधे जोडा-टाइम का उपयोग करना सरल है, और मैंने कभी किसी को ऐसा करते हुए नहीं देखा है।)
बर्बाद

@amon "मेरे पास घड़ियों के समान अनुभव है जहां आप स्पष्ट रूप से वास्तविक समय के अलावा कभी भी कुछ नहीं चाहते हैं, सही समय को छोड़कर; समय क्षेत्र / डीएसटी किनारे के मामलों का परीक्षण करते समय ..." - या जब आपको पता चलता है कि बग है आपके डेटाबेस को दूषित कर दिया है और इसे वापस पाने की एकमात्र आशा है कि आप अपने ईवेंट लॉग को पार्स करें और इसे अंतिम बैकअप से शुरू करें ... लेकिन अचानक आपको वर्तमान के बजाय वर्तमान लॉग प्रविष्टि के टाइमस्टैम्प के आधार पर काम करने के लिए अपने सभी कोड की आवश्यकता होती है समय।
जूल्स

3

हां और नहीं, लेकिन ज्यादातर नहीं

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

स्टैटिक्स का उपयोग कब करना ठीक है? क्योंकि स्पष्ट रूप से यह कभी-कभी ठीक है। हां जवाब अमूर्तता के लाभ और "नहीं" जवाब बताते हैं कि वे आपके लिए कुछ भुगतान करते हैं। एक कारण यह है कि आपकी नौकरी कठिन है, ऐसा कोई जवाब नहीं है जिसे आप लिख सकते हैं और सभी स्थितियों पर लागू कर सकते हैं।

लेना: Convert.ToInt32("1")

मुझे यह पसंद है:

private readonly IConverter _converter;

public MyClass(IConverter converter)
{
   Guard.NotNull(converter)
   _converter = conveter
}

.... 
var foo = _converter.ToInt32("1");

क्यों? मैं स्वीकार कर रहा हूं कि मुझे रूपांतरण कोड को स्वैप करने के लिए लचीलेपन की आवश्यकता है, तो मुझे कोड को फिर से भरना होगा। मैं यह स्वीकार कर रहा हूं कि मैं इसका मजाक नहीं उड़ा पाऊंगा। मेरा मानना ​​है कि सादगी और मर्यादा इस व्यापार के लायक है।

स्पेक्ट्रम के दूसरे छोर को देखते हुए, यदि IConverterएक था SqlConnection, मैं काफी देखने के लिए कि एक स्थिर कॉल के रूप में भयभीत कर दिया जाएगा। कारण स्पष्ट रूप से स्पष्ट हैं। मैं SQLConnectionबताता हूं कि एक प्रशंसा में काफी "क्रॉस-कटिंग" हो सकता है, इसलिए मैंने उन सटीक शब्दों का उपयोग नहीं किया होगा।

क्या लॉगिंग अधिक पसंद है SQLConnectionया Convert.ToInt32? मैं और अधिक कहना चाहूँगा 'SQLConnection`।

आपको लॉगिंग का मजाक बनाना चाहिए । यह बाहरी दुनिया से बात करता है। उपयोग करने की एक विधि लिखते समय Convert.ToIn32, मैं इसे कक्षा के कुछ अलग-अलग परीक्षण योग्य आउटपुट की गणना करने के लिए एक उपकरण के रूप में उपयोग कर रहा हूं। मुझे यह जांचने की आवश्यकता नहीं है Convertकि "1" + "2" == "3" की जाँच करते समय सही ढंग से कॉल किया गया था। लॉगिंग अलग है, यह क्लास का पूरी तरह से इंडिपेंडेंट आउटपुट है। मैं मान रहा हूँ कि यह एक आउटपुट है, जिसका मूल्य आपके लिए है, समर्थन टीम और व्यवसाय। यदि लॉगिंग सही नहीं है, तो आपकी कक्षा काम नहीं कर रही है, इसलिए इकाई परीक्षण पास नहीं होना चाहिए। आपको परीक्षण करना चाहिए कि आपकी कक्षा क्या लॉग करती है। मुझे लगता है कि यह हत्यारा तर्क है, मैं वास्तव में यहां रुक सकता हूं।

मुझे भी लगता है कि यह कुछ ऐसा है जो बदलने की काफी संभावना है। अच्छा लॉगिंग केवल तार नहीं छापता है, यह एक दृश्य है कि आपका आवेदन क्या कर रहा है (मैं इवेंट आधारित लॉगिंग का एक बड़ा प्रशंसक हूं)। मैंने काफी विस्तृत रिपोर्टिंग UI में बेसिक लॉगिंग टर्न देखा है। यह स्पष्ट रूप से इस दिशा में सिर करने के लिए बहुत आसान है अगर आपका लॉगिंग जैसा दिखता है _logger.Log(new ApplicationStartingEvent())और कम पसंद करता है Logger.Log("Application has started")। कोई यह तर्क दे सकता है कि यह भविष्य के लिए इन्वेंट्री बना रहा है जो कभी नहीं हो सकता है, यह एक निर्णय कॉल है और मुझे लगता है कि यह इसके लायक है।

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

इसलिए मैं लॉगिंग के मामले के लिए टेलस्टीन के साथ सहमत हूं।


यह है कि मैं कैसे लॉग इन करें । मैं एक लेख या कुछ और से लिंक करना चाहता हूं, लेकिन मुझे एक नहीं मिल रहा है। यदि आप .NET दुनिया में हैं, और इवेंट लॉगिंग देखते हैं, तो आप पाएंगे Semantic Logging Application Block। इसका उपयोग न करें, जैसे एमएस "पैटर्न और प्रैटिस" टीम द्वारा बनाए गए अधिकांश कोड, विडंबना यह है कि यह एक एंटीपैटर्न है।
नाथन कूपर

3

पहली क्रॉस कटिंग चिंताएं प्रमुख बिल्डिंग ब्लॉक्स नहीं हैं और इसे सिस्टम में निर्भरता के रूप में नहीं माना जाना चाहिए। अगर लॉगर को इनिशियलाइज़ नहीं किया जाता है या कैश काम नहीं कर रहा है तो एक सिस्टम को काम करना चाहिए। आप सिस्टम को कम युग्मित और एकजुट कैसे करेंगे? यहीं SOLO OO सिस्टम डिजाइन में चित्र में आता है।

ऑब्जेक्ट को एकल के रूप में रखने से SOLID का कोई लेना देना नहीं है। यह आपका ऑब्जेक्ट जीवन चक्र है कि आप कितने समय तक ऑब्जेक्ट को मेमोरी में रहना चाहते हैं।

एक वर्ग जिसे शुरू करने के लिए एक निर्भरता की आवश्यकता होती है, उसे पता नहीं होना चाहिए कि आपूर्ति की गई कक्षा एकल है या क्षणिक। लेकिन tldr; यदि आप Logger.Instance.Log () हर विधि या वर्ग में लिख रहे हैं तो यह समस्याग्रस्त कोड (कोड गंध / हार्ड युग्मन) वास्तव में एक गड़बड़ है। यह वह क्षण होता है जब लोग SOLID का दुरुपयोग करना शुरू कर देते हैं। और ओपी जैसे साथी डेवलपर्स इस तरह से वास्तविक सवाल पूछना शुरू करते हैं।


2

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


दिलचस्प। मैंने कभी भी किसी ऐसी भाषा का उपयोग करके कोई महत्वपूर्ण काम नहीं किया है जो लक्षणों का समर्थन करता है, लेकिन मैंने कुछ भविष्य की परियोजनाओं के लिए ऐसी भाषाओं का उपयोग करने पर विचार किया है, इसलिए यह मेरे लिए उपयोगी होगा यदि आप इस पर विस्तार कर सकते हैं, और दिखा सकते हैं कि लक्षण समस्या को कैसे हल करते हैं।
जूल्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.