ग्लोबल स्टेट इतना ईविल क्यों है?


328

इससे पहले कि हम इसे शुरू करें, मैं कहता हूं कि मैं एब्सट्रैक्शन और डिपेंडेंसी इंजेक्शन की अवधारणाओं से अच्छी तरह परिचित हूं। मुझे अपनी आँखें यहाँ खोलने की आवश्यकता नहीं है।

ठीक है, हम में से अधिकांश कहते हैं, (भी) कई बार वास्तव में समझ के बिना, "वैश्विक चर का उपयोग न करें", या "सिंगलटन बुराई कर रहे हैं क्योंकि वे वैश्विक हैं"। लेकिन वास्तव में अशुभ वैश्विक राज्य के बारे में इतना बुरा क्या है ?

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

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

मैं जानता हूँ कि यह करने के लिए बुरा है दुरुपयोग यह है, लेकिन वैश्विक अंतरिक्ष वास्तव में है कि बुराई? और अगर यह है, तो क्या अच्छे विकल्प हैं?


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

25
वैश्विक उपयोग करने के साथ अंतर कहां है? आपकी "एक और केवल एक जगह" बहुत ही संदिग्ध रूप से सिंगलटन की तरह लगती है।
मदारा उचिहा

130
एकमात्र वास्तविक बुराई हठधर्मिता है।
पीटर बी

34
अपने साथी प्रोग्रामरों के साथ वैश्विक स्थिति का उपयोग करना अपने दोस्तों के साथ एक ही टूथब्रश का उपयोग करने जैसा है - आप कर सकते हैं लेकिन आप कभी नहीं जानते कि कब कोई इसे अपने चूतड़ को उछालने का फैसला करेगा।
जिजी

5
शैतान दुष्ट है। वैश्विक स्थिति न तो बुराई है और न ही अच्छी है। आप इसका उपयोग कैसे करते हैं, इसके आधार पर यह बहुत उपयोगी या हानिकारक हो सकता है। दूसरों की न सुनें और ठीक से प्रोग्राम करना सीखें।
कष्टप्रद_

जवाबों:


282

बहुत संक्षेप में, यह कार्यक्रम की स्थिति को अप्रत्याशित बनाता है।

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

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

शैक्षणिक स्तर पर यह सब गंभीर नहीं लग सकता है, लेकिन इकाई परीक्षण कोड में सक्षम होना इसकी शुद्धता (या उद्देश्य के लिए कम से कम फिटनेस) साबित करने की प्रक्रिया में एक बड़ा कदम है।

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

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

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

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

कई अन्य कारण हैं कि वैश्विक राज्य पर भरोसा करने के लिए राज्य के आसपास से गुजरना काफी हद तक बेहतर है। यह उत्तर किसी भी तरह से व्यापक नहीं है। आप शायद पूरी किताब लिख सकते हैं कि वैश्विक स्थिति क्यों खराब है।


61
असल में, क्योंकि कोई भी राज्य को बदल सकता है, आप उस पर भरोसा नहीं कर सकते।
Oded

21
@Truth विकल्प? निर्भरता इंजेक्शन
rdlowrey

12
आपका मुख्य तर्क वास्तव में उस चीज़ पर लागू नहीं होता है जो प्रभावी रूप से केवल-पढ़ने के लिए है, जैसे कि कॉन्फ़िगरेशन का प्रतिनिधित्व करने वाली वस्तु।
फ्रैंक

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

20
being able to unit test code is a major step in the process of proving its correctness (or at least fitness for purpose)। नहीं, यह नहीं है। "अब दो दशक हो गए हैं क्योंकि यह बताया गया था कि कार्यक्रम परीक्षण निश्चित रूप से बग की उपस्थिति को प्रदर्शित कर सकता है, लेकिन कभी भी उनकी अनुपस्थिति को प्रदर्शित नहीं कर सकता है। इस अच्छी तरह से प्रचारित टिप्पणी को श्रद्धापूर्वक उद्धृत करने के बाद, सॉफ्टवेयर इंजीनियर दिन के क्रम पर लौटता है और जारी रहता है।" अपनी परीक्षण रणनीतियों को निखारने के लिए, योर के कीमियागर की तरह, जो अपने क्राइसोकोमिकम योग्यता को परिष्कृत करना जारी रखा। " - Djikstra, 1988. (कि अब यह 4.5 दशक का हो जाता है ...)
मेसन व्हीलर

135

म्यूटेबल ग्लोबल स्टेट कई कारणों से बुराई है:

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

परिवर्तनशील वैश्विक स्थिति के विकल्प:

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

11
मुझे लगता है कि संदर्भ पैरामीटर या निर्भरता इंजेक्शन द्वारा किसी संदर्भ वस्तु को पास करने से समस्या उत्पन्न होती है यदि संदर्भ परिवर्तनशील है, समान समस्या जो पारस्परिक वैश्विक स्थिति का उपयोग कर रही है।
अल्फ्रेडो ओसोरियो

1
सभी अच्छे सामान, और आमीन! लेकिन सवाल अपरिवर्तनीय वैश्विक स्थिति के बारे में है
मार्कजे

@ अल्फ्रेडो - बहुत सही। हालांकि यह उतना बुरा नहीं है क्योंकि कम से कम दायरे को कुछ हद तक नियंत्रित किया जा सकता है। लेकिन सामान्य तौर पर, संदर्भ और निर्भरता को अपरिवर्तनीय बनाकर समस्या को हल करना आसान होता है।
मिकेरा

2
उत्परिवर्तनीय / अपरिवर्तनीय के लिए +1। अपरिवर्तनीय ग्लोबल्स ठीक हैं। यहां तक ​​कि वे जो आलसी हैं, लेकिन कभी नहीं बदलते हैं। बेशक, वैश्विक चर, लेकिन एक वैश्विक इंटरफ़ेस या एपीआई को उजागर न करें।
जेस

1
@giorgio यह सवाल स्पष्ट करता है कि विचाराधीन चर स्टार्टअप पर अपने मूल्यों को प्राप्त करते हैं और कार्यक्रम निष्पादन (सिस्टम फ़ोल्डर, डेटाबेस क्रेडेंशियल्स) के दौरान बाद में कभी नहीं बदलते हैं। यानी अपरिवर्तनीय, यह एक बार बदल नहीं जाता है क्योंकि इसे एक मूल्य दिया गया है। व्यक्तिगत रूप से मैं "राज्य" शब्द का भी उपयोग करता हूं क्योंकि यह एक निष्पादन से दूसरे तक, या एक अलग मशीन पर अलग हो सकता है। बेहतर शब्द हो सकते हैं।
मार्क

62
  1. चूंकि आपका पूरा लानत ऐप इसका उपयोग कर सकता है, इसलिए उन्हें फिर से वापस करने के लिए हमेशा अविश्वसनीय रूप से कठिन होता है। यदि आप कभी भी अपने वैश्विक के साथ कुछ भी करने के लिए बदलते हैं, तो आपके सभी कोड बदलने की जरूरत है। यह एक रखरखाव सिरदर्द है- grepटाइप नाम के लिए यह पता लगाने में सक्षम होने से कहीं अधिक है कि कौन से कार्य इसका उपयोग करते हैं।
  2. वे खराब हैं क्योंकि वे छिपी हुई निर्भरता का परिचय देते हैं, जो मल्टीथ्रेडिंग को तोड़ते हैं, जो तेजी से कई अनुप्रयोगों के लिए महत्वपूर्ण है।
  3. वैश्विक चर की स्थिति हमेशा पूरी तरह से अविश्वसनीय है, क्योंकि आपके सभी कोड इसके लिए कुछ भी कर सकते हैं।
  4. वे वास्तव में परीक्षण करने के लिए कठिन हैं।
  5. वे एपीआई को कठिन बनाते हैं। "आपको एपीआई को कॉल करने से पहले SET_MAGIC_VARIABLE () को कॉल करना याद रखना चाहिए" बस किसी से भीख मांगना भूल जाता है। यह एपीआई त्रुटि-प्रवण का उपयोग करता है, जिससे मुश्किल-से-मुश्किल कीड़े हो जाते हैं। इसे एक नियमित पैरामीटर के रूप में उपयोग करके, आप कॉलर को उचित मूल्य प्रदान करने के लिए मजबूर करते हैं।

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


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

6
@ कोडर: ध्यान दें कि वैश्विक के लिए वैकल्पिक विकल्प "कोड में 1000x स्थानों से पाठकों को कॉन्फ़िगर नहीं करता है", लेकिन एक कॉन्फ़िगर रीडर, जो एक कॉन्फ़िगर ऑब्जेक्ट बनाता है, जो विधियां पैरामीटर (-> निर्भरता इंजेक्शन) के रूप में स्वीकार कर सकती हैं।
sleske

2
नाइटपैकिंग: एक वैश्विक की तुलना में एक प्रकार के लिए पकड़ना क्यों आसान है? और सवाल केवल-पढ़ने योग्य ग्लोबल्स के बारे में है, इसलिए बिंदु 2 और 3 प्रासंगिक नहीं हैं
MarkJ

2
@ मर्कज: मुझे उम्मीद है कि कोई भी, कभी भी, नाम नहीं बताएगा।
डेडएमजी

2
@DeadMG, Re ".. हमेशा पूरी तरह से अविश्वसनीय ..", वही निर्भरता इंजेक्शन के लिए जाता है। सिर्फ इसलिए कि आपने इसे एक पैरामीटर बना दिया है, इसका मतलब यह नहीं है कि ओब्जेक्ट को एक निश्चित स्थिति की गारंटी है। फ़ंक्शन के नीचे कहीं आप किसी अन्य फ़ंक्शन को कॉल कर सकते हैं जो शीर्ष पर अंतःस्थापित चर की स्थिति को संशोधित करता है।
पचेरियर

34

यदि आप "राज्य" कहते हैं, तो इसका अर्थ आमतौर पर "उत्परिवर्ती राज्य" होता है। और वैश्विक उत्परिवर्ती राज्य पूरी तरह से बुराई है, क्योंकि इसका मतलब है कि कार्यक्रम का कोई भी हिस्सा किसी अन्य भाग (वैश्विक स्थिति को बदलकर) को प्रभावित कर सकता है

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

आप उन स्थानों की तलाश करते हैं जो x को संशोधित करते हैं , और पाते हैं कि पांच स्थान हैं जो इसे संशोधित करते हैं। अब अच्छी किस्मत यह बताती है कि ए क्या काम करता है।


इतनी अपरिवर्तनीय वैश्विक स्थिति इतनी बुरी नहीं है?
फ्रस्ट्रेटेडविथफॉर्म्सडिजेनर

50
मैं कहूंगा कि अपरिवर्तनीय वैश्विक स्थिति अच्छी तरह से ज्ञात अच्छा अभ्यास है जिसे 'स्थिरांक' के रूप में जाना जाता है।
तेलस्तीन

6
अपरिवर्तनीय वैश्विक स्थिति बुराई नहीं है, यह सिर्फ बुरा है :-)। यह अभी भी समस्याग्रस्त है क्योंकि युग्मन के कारण यह (परिवर्तन, पुन: उपयोग और इकाई परीक्षण कठिन बनाता है) करता है, लेकिन बहुत कम समस्याएं पैदा करता है, इसलिए सरल मामलों में यह आमतौर पर स्वीकार्य होता है।
sleske

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

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

9

आप अपने खुद के सवाल का जवाब दिया। जब उनका दुरुपयोग किया जाता है, तो उन्हें प्रबंधित करना मुश्किल होता है, लेकिन उपयोगी होने पर [कुछ हद तक] अनुमान लगाया जा सकता है और उनका उपयोग करने का तरीका जानने वाला कोई व्यक्ति। ग्लोबल्स पर रखरखाव और / के लिए परिवर्तन आमतौर पर एक दुःस्वप्न होता है, जो आवेदन के आकार में वृद्धि के रूप में खराब हो जाता है।

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

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


9

सिंग्लेटन्स के साथ कई समस्याएं हैं - यहां मेरे दिमाग में दो सबसे बड़ी समस्याएं हैं।

  • यह इकाई परीक्षण को समस्याग्रस्त बनाता है। वैश्विक राज्य एक परीक्षण से दूसरे तक दूषित हो सकता है

  • यह "वन-एंड-ओनली-वन" हार्ड नियम को लागू करता है, जो, भले ही यह संभवतः बदल नहीं सकता, अचानक करता है। उपयोगिता कोड का एक पूरा गुच्छा, जो विश्व स्तर पर सुलभ वस्तु का उपयोग करता है, तब उसे बदलना होगा।

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

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

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

आप रखरखाव की नई समस्याओं में भाग लेते हैं। एक उदाहरण: अचानक आपका "विजेट", ग्राफ में गहरे घटक को एक टाइमर ऑब्जेक्ट की आवश्यकता होती है जिसे आप मॉक आउट करना चाहते हैं। हालाँकि, "WidgetFactory" "WidgetBuilder" द्वारा बनाया गया है, जो "WidgetCreationManager" का हिस्सा है, और आपको इस टाइमर ऑब्जेक्ट के बारे में जानने के लिए तीन वर्गों की आवश्यकता है, भले ही केवल एक ही वास्तव में इसका उपयोग करता हो। आप खुद को छोड़ देना चाहते हैं और सिंगलेट्स पर वापस जाना चाहते हैं, और इस टाइमर ऑब्जेक्ट को विश्व स्तर पर सुलभ बना सकते हैं।

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

तो, सारांश में, सिंग्लेटन्स खराब हैं, और विकल्प एक निर्भरता इंजेक्शन ढांचे का उपयोग करना है।

मैं कैसल विंडसर का उपयोग करने के लिए होता हूं, लेकिन आप पसंद के लिए खराब हो गए हैं। उपलब्ध रूपरेखाओं की सूची के लिए इस पृष्ठ को 2008 में पीछे से देखें ।


8

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

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

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

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


4

चूंकि कुछ अन्य उत्तर यहाँ के बीच भेद करना परिवर्तनशील और अपरिवर्तनीय वैश्विक राज्य, मैं विचार करने के लिए कि चाहते हैं यहां तक कि अपरिवर्तनीय वैश्विक चर / सेटिंग्स अक्सर एक झुंझलाहट हैं

प्रश्न पर विचार करें:

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

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

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


3

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

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

(यह कुछ यादृच्छिक उदाहरण नहीं है ... यह उस परियोजना में हमारे कॉन्फ़िगरेशन सिस्टम के साथ हुआ है जो मैं वर्तमान में हूं।)

यह देखते हुए कि आमतौर पर कुछ गैर-वैश्विक बनाने की लागत तुच्छ है, ऐसा करना मूर्खतापूर्ण है। आप सिर्फ भविष्य की समस्याएं पैदा कर रहे हैं।


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

3

दूसरी समस्या यह है कि वे बड़े पैमाने पर एक आवेदन को कठिन बनाते हैं क्योंकि थाय पर्याप्त "वैश्विक" नहीं हैं। एक वैश्विक चर का दायरा प्रक्रिया है।

यदि आप कई प्रक्रियाओं का उपयोग करके या आप नहीं कर सकते हैं, तो कई प्रक्रियाओं का उपयोग करके अपने आवेदन को स्केल करना चाहते हैं। कम से कम तब तक नहीं जब तक आप सभी ग्लोबल्स को खत्म नहीं कर देते और उन्हें किसी अन्य तंत्र से बदल नहीं देते।


3

ग्लोबल स्टेट इतना ईविल क्यों है?

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

इसलिए, हम डिबगिंग या किसी ऑब्जेक्ट का परीक्षण करने में बहुत खराब हैं जिसका व्यवहार किसी प्रोग्राम के निष्पादन के दौरान परिवर्तित होने के कुछ बाहरी कारणों से अधिक है। अकेले चलो जब हमें इनमें से दर्जनों वस्तुओं को एक साथ लेना होता है।


3

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

जो-ई एक उदाहरण है, और डेविड वैगनर इस निर्णय को स्पष्ट करते हैं:

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

तो इसके बारे में सोचने का एक तरीका है

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

इसलिए, विश्व स्तर पर उत्परिवर्तनीय स्थिति इसे कठिन बना देती है

  1. मजबूत सिस्टम डिजाइन,
  2. एक प्रणाली के गुणों को साबित करने के लिए कठिन है, और
  3. यह सुनिश्चित करना कठिन है कि आपके परीक्षण आपके उत्पादन वातावरण के समान दायरे में परीक्षण कर रहे हैं।

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


2

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

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

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

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

इसके अलावा: समस्याएँ बढ़ रही हैं:

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

if (filePath != null)  text = filePath.getName();

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

ग्लोबल्स में निश्चित रूप से यह समस्या है, और यदि आप उन्हें पूरी तरह से समाप्त कर सकते हैं या उन्हें स्थिरांक या स्थानीय चर के साथ बदल सकते हैं, तो यह बहुत अच्छी बात है। यदि आपके पास वेब सर्वर पर स्टेटलेस कोड चल रहा है, तो आप शायद कर सकते हैं। आमतौर पर, आपकी सभी मल्टीथ्रेडिंग समस्याओं को डेटाबेस द्वारा लिया जा सकता है।

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


1
क्या आप इसका मतलब स्पष्ट कर सकते हैं ?: "जो कुछ भी स्थानीय चर या अपरिवर्तनीय क्षेत्र नहीं है वह एक समस्या है। ग्लोबल्स इस तरह की समस्या है, लेकिन आप उन्हें गैर-वैश्विक बनाकर ठीक नहीं करने जा रहे हैं।"
एंड्रेस एफ

1
@AndresF .: मैंने अपना जवाब बढ़ाया। मुझे लगता है कि मैं एक डेस्कटॉप दृष्टिकोण ले रहा हूं जहां इस पृष्ठ पर अधिकांश लोग अधिक सर्वर-कोड-ए-डेटाबेस हैं। "ग्लोबल" का मतलब इन मामलों में अलग-अलग हो सकता है।
राल्फचैपिन

2

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

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

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


1

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

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


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

1

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

वैश्विक राज्य के लिए, ऐसा कोई मुद्दा नहीं है, सब कुछ वैश्विक है।

उदाहरण के लिए: निम्न परिदृश्य की कल्पना करें: आपके पास एक 10x10 ग्रिड है जो कि "बोर्ड" और "टाइल" से बना है।

यदि आप इसे ओओपी तरीके से करना चाहते हैं, तो आप प्रत्येक "टाइल" के लिए "बोर्ड" ऑब्जेक्ट पास करेंगे। मान लें कि अब "टाइल" में 2 "बाइट" प्रकार के फ़ील्ड हैं जो इसे समन्वित करते हैं। एक टाइल के लिए 32 बिट मशीन पर कुल मेमोरी होगी (1 + 1 + 4 = 6) बाइट्स: 1 के लिए x कॉर्ड, 1 के लिए y कॉर्ड और 4 के लिए एक पॉइंटर। यह 10x10 टाइल्स सेटअप के लिए कुल 600 बाइट्स देता है

अब उस मामले के लिए जहां बोर्ड वैश्विक दायरे में है, प्रत्येक टाइल से सुलभ एक एकल वस्तु आपको केवल प्रत्येक टाइल के प्रति 2 बाइट्स प्राप्त करना होगा, यह x और y समन्वित बाइट्स है। यह केवल 200 बाइट्स देगा।

तो इस मामले में आपको स्मृति उपयोग का 1/3 हिस्सा मिलता है यदि आप केवल वैश्विक स्थिति का उपयोग करते हैं।

यह, अन्य बातों के अलावा, मुझे लगता है कि एक कारण है कि वैश्विक स्कोप अभी भी सी + ++ जैसी निम्न स्तर की भाषाओं में बना हुआ है


1
यह भाषा पर अत्यधिक निर्भर है। उन भाषाओं में जहां कार्यक्रम लगातार चलते हैं, यह सच हो सकता है कि आप कई कक्षाओं को तुरंत करने के बजाय वैश्विक स्थान और एकल का उपयोग करके स्मृति को बचाने में सक्षम हैं, लेकिन यह तर्क भी अस्थिर है। यह सभी प्राथमिकताओं के बारे में है। PHP जैसी भाषाओं में (जो अनुरोध के अनुसार एक बार चलाई जाती है, और वस्तुएं बनी नहीं रहती हैं), यहां तक ​​कि तर्क भी मूट है।
मदार उचिहा

1
@ मादारूचिहा नहीं, यह तर्क किसी भी तरह से अस्थिर नहीं है। यह वस्तुनिष्ठ तथ्य हैं, जब तक कि कुछ VM या अन्य संकलित भाषा इस तरह के मुद्दे के साथ कुछ कट्टर कोड अनुकूलन नहीं करती है। अन्यथा यह अभी भी प्रासंगिक है। यहां तक ​​कि सर्वर साइड प्रोग्राम के साथ जो मेमोरी "एक शॉट" का उपयोग करते हैं, निष्पादन के समय के माध्यम से मेमोरी आरक्षित होती है। एक उच्च लोड सर्वर के साथ यह एक महत्वपूर्ण बिंदु हो सकता है।
luke1985

0

वैश्विक राज्य के साथ विचार करने के लिए कई कारक हैं:

  1. प्रोग्रामर मेमोरी स्पेस
  2. अपरिवर्तनीय ग्लोबल्स / एक बार ग्लोबल्स लिखें।
  3. म्यूटेबल ग्लोबल्स
  4. ग्लोबल्स पर निर्भरता।

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

Immutables / लिखना एक बार आम तौर पर ठीक होता है, लेकिन प्रारंभ अनुक्रम अनुक्रम त्रुटियों के लिए देखें।

म्यूटेबल ग्लोबल्स को अक्सर अपरिवर्तनीय ग्लोबल्स के लिए गलत माना जाता है ...

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

वैश्विक स्थिति बुराई नहीं है, लेकिन यह एक निश्चित लागत पर आती है - इसका उपयोग तब करें जब लाभ लागत से आगे निकल जाए।

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