एक चर राज्य कैसे पेश करता है?


11

मैं "C ++ कोडिंग मानक" पढ़ रहा था और यह पंक्ति वहां थी:

चर राज्य का परिचय देते हैं, और आपको यथासंभव कम जीवनकाल के साथ कम से कम स्थिति से निपटना चाहिए।

कुछ भी नहीं है कि उत्परिवर्ती अंततः राज्य में हेरफेर करता है? जितना संभव हो उतना कम राज्य से निपटने के लिए आपके पास क्या होना चाहिए ?

C ++ जैसी अशुद्ध भाषा में, क्या राज्य प्रबंधन वास्तव में आप क्या कर रहे हैं? और चर जीवनकाल को सीमित करने के अलावा जितना संभव हो उतना कम राज्य से निपटने के अन्य तरीके क्या हैं ?

जवाबों:


16

क्या कोई भी परिवर्तनशील वस्तु वास्तव में राज्य में हेरफेर नहीं करती है?

हाँ।

और "आपको छोटे राज्य से निपटने के लिए क्या करना चाहिए" का मतलब है?

इसका मतलब है कि कम राज्य अधिक राज्य से बेहतर है। अधिक राज्य अधिक जटिलता का परिचय देता है।

C ++ जैसी अशुद्ध भाषा में, क्या राज्य प्रबंधन वास्तव में आप क्या कर रहे हैं?

हाँ।

चर जीवनकाल को सीमित करने के अलावा "थोड़ा राज्य से निपटने" के अन्य तरीके क्या हैं?

चरों की संख्या कम से कम करें। पृथक कोड जो कुछ राज्य को एक स्व-निहित इकाई में हेरफेर करता है ताकि अन्य कोड अनुभाग इसे अनदेखा कर सकें।


9

क्या कोई भी परिवर्तनशील वस्तु वास्तव में राज्य में हेरफेर नहीं करती है?

हाँ। C ++ में, केवल परिवर्तनशील चीजें (गैर- const) चर हैं।

और "आपको छोटे राज्य से निपटने के लिए क्या करना चाहिए" का मतलब है?

एक कार्यक्रम में जितना कम राज्य होता है, यह समझना उतना आसान होता है कि वह क्या करता है। इसलिए आपको उस राज्य का परिचय नहीं देना चाहिए, जिसकी आपको आवश्यकता नहीं है, और आपको इसकी आवश्यकता नहीं होने के बाद इसे नहीं रखना चाहिए।

C ++ जैसी अशुद्ध भाषा में, क्या राज्य प्रबंधन वास्तव में आप क्या कर रहे हैं?

C ++ जैसी बहु-प्रतिमान भाषा में, अक्सर "शुद्ध" कार्यात्मक या राज्य द्वारा संचालित दृष्टिकोण या किसी प्रकार के संकर के बीच एक विकल्प होता है। ऐतिहासिक रूप से, कार्यात्मक प्रोग्रामिंग के लिए भाषा समर्थन कुछ भाषाओं की तुलना में काफी कमजोर रहा है, लेकिन इसमें सुधार हो रहा है।

चर जीवनकाल को सीमित करने के अलावा "थोड़ा राज्य से निपटने" के अन्य तरीके क्या हैं?

वस्तुओं के बीच युग्मन को कम करने के लिए जीवनकाल के साथ-साथ गुंजाइश को सीमित करें; वैश्विक चर के बजाय स्थानीय और सार्वजनिक वस्तु के सदस्यों के बजाय निजी।


5

राज्य का मतलब है कि कुछ कहीं संग्रहीत किया जा रहा है ताकि आप इसे बाद में संदर्भित कर सकें।

एक वैरिएबल बनाना, कुछ डेटा स्टोर करने के लिए आपके लिए कुछ जगह बनाता है। यह डेटा आपके प्रोग्राम की स्थिति है।

आप इसका उपयोग चीजों को करने, इसे बदलने, इसके साथ गणना करने आदि के लिए करते हैं।

यह वह जगह है राज्य है, जबकि चीजें आप कर राज्य नहीं हैं।

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

C ++ में आप फंक्शन ऑब्जेक्ट्स बना सकते हैं , जो structया ऐसे classप्रकार हैं जो operator()()ओवरलोडेड हैं। इन फ़ंक्शन ऑब्जेक्ट्स में स्थानीय स्थिति हो सकती है, हालांकि यह आपके प्रोग्राम में अन्य कोड के बीच आवश्यक रूप से साझा नहीं किया गया है। फंडर्स (यानी फंक्शन ऑब्जेक्ट्स) को पास करना बहुत आसान है। यह लगभग उतना ही है जितना कि आप C ++ में एक कार्यात्मक प्रतिमान की नकल कर सकते हैं। (AFAIK)

कम या कोई राज्य नहीं होने का मतलब है कि आप समानांतर निष्पादन के लिए अपने कार्यक्रम को आसानी से अनुकूलित कर सकते हैं, क्योंकि ऐसा कुछ भी नहीं है जो थ्रेड्स या सीपीयू के बीच साझा किया जा सकता है, इसलिए कुछ भी नहीं है जिसके बारे में विवाद पैदा किया जा सकता है, और कुछ भी नहीं जो आपको डेटा दौड़ से बचाना है, आदि।


2

अन्य लोगों ने पहले 3 प्रश्नों के अच्छे उत्तर दिए हैं।

और चर जीवनकाल को सीमित करने के अलावा "यथासंभव छोटी स्थिति से निपटने" के अन्य तरीके क्या हैं?

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

अन्यथा आप राज्य के प्रभाव को सीमित कर रहे हैं; या तो दृश्यता या जीवनकाल के माध्यम से।


1

और "आपको छोटे राज्य से निपटने के लिए क्या करना चाहिए" का मतलब है?

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


1

यह समझने के लिए कि एक कार्यक्रम कैसे काम करता है, आपको इसकी अवस्थाओं को समझना चाहिए। आपके पास जितना कम राज्य होगा और उसका उपयोग करने वाले कोड के लिए उतना ही अधिक स्थानीय होगा, यह उतना ही आसान होगा।

यदि आपने कभी ऐसे प्रोग्राम के साथ काम किया है जिसमें बड़ी संख्या में वैश्विक वैरिएबल होते हैं तो आप निहित रूप से समझ जाएंगे।


1

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

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

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


1

कुछ भी नहीं है कि उत्परिवर्ती अंततः राज्य में हेरफेर करता है?

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

जितना संभव हो उतना कम राज्य से निपटने के लिए आपके पास क्या होना चाहिए?

चर के दृष्टिकोण से: कोड की कुछ पंक्तियों को संभव के रूप में उपयोग करने में सक्षम होना चाहिए। चर के दायरे को न्यूनतम तक सीमित करें।

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

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

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

C ++ जैसी अशुद्ध भाषा में, क्या राज्य प्रबंधन वास्तव में आप क्या कर रहे हैं?

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

और चर जीवनकाल को सीमित करने के अलावा जितना संभव हो उतना कम राज्य से निपटने के अन्य तरीके क्या हैं?

ये सभी एक चर के दायरे को सीमित करने के दायरे में हैं, लेकिन ऐसा करने के कई तरीके हैं:

  • प्लेग जैसे कच्चे वैश्विक चर से बचें। यहां तक ​​कि कुछ गूंगा वैश्विक सेटर / गेट्टर फ़ंक्शन उस चर की दृश्यता को काफी कम कर देता है, और कम से कम हमलावरों को बनाए रखने के कुछ तरीके की अनुमति देता है (उदाहरण के लिए: यदि वैश्विक चर को कभी भी नकारात्मक मूल्य की अनुमति नहीं दी जानी चाहिए, तो सेटर अपरिवर्तनीय बनाए रख सकता है)। निश्चित रूप से, यहां तक ​​कि एक वैश्विक परिवर्तनक के रूप में एक सेट्टर / गेट्टर डिज़ाइन भी बहुत खराब डिज़ाइन होगा, मेरा कहना सिर्फ इतना है कि यह अभी भी बेहतर है।
  • जब संभव हो अपनी कक्षाओं को छोटा करें। सैकड़ों सदस्य कार्यों के साथ एक वर्ग, 20 सदस्य चर, और इसे लागू करने वाले कोड की 30,000 पंक्तियों के बजाय "वैश्विक" निजी चर होंगे, क्योंकि उन सभी चर अपने सदस्य कार्यों के लिए सुलभ होंगे जिनमें कोड की 30k लाइनें शामिल हैं। आप उस मामले में "राज्य जटिलता" कह सकते हैं, जबकि प्रत्येक सदस्य फ़ंक्शन में स्थानीय चर को छूट देता है 30,000*20=600,000। यदि उसके शीर्ष पर 10 वैश्विक चर सुलभ थे, तो राज्य की जटिलता हो सकती है 30,000*(20+10)=900,000। एक स्वस्थ "राज्य जटिलता" (मेरी व्यक्तिगत प्रकार की आविष्कार की गई मीट्रिक) कक्षाओं के लिए हजारों या नीचे होनी चाहिए, न कि हजारों में, और निश्चित रूप से सैकड़ों हजारों में नहीं। नि: शुल्क कार्यों के लिए, हम रखरखाव में गंभीर सिरदर्द प्राप्त करने के लिए शुरू करने से पहले सैकड़ों या उससे कम कहते हैं।
  • ऊपर के समान नस में, सदस्य फ़ंक्शन या मित्र फ़ंक्शन के रूप में कुछ लागू नहीं करते हैं जो अन्यथा केवल गैर-वर्ग हो सकते हैं, केवल कक्षा के सार्वजनिक इंटरफ़ेस का उपयोग करते हुए गैर-मित्र। ऐसे फ़ंक्शंस कक्षा के निजी चर तक नहीं पहुँच सकते हैं, और इस तरह उन निजी चर के दायरे को कम करके त्रुटि की संभावना को कम करते हैं।
  • किसी फ़ंक्शन में वास्तव में आवश्यक होने से बहुत पहले ही चर घोषित करने से बचें (यानी, विरासत सी शैली से बचें जो किसी फ़ंक्शन के शीर्ष पर सभी चर की घोषणा करते हैं, भले ही उन्हें केवल नीचे कई लाइनें चाहिए)। यदि आप इस शैली का उपयोग वैसे भी करते हैं, तो कम से कम कार्यों के लिए प्रयास करें।

वेरिएबल्स से परे: साइड इफेक्ट्स

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

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

ऐसे मामलों में, "राज्य" का विचार कच्चे चर से परे है, और सिर्फ डेटा संरचनाओं और उस तरह की चीजों से परे है। इसी तरह यह उनके दायरे को कम करने में मदद करता है (लाइनों की संख्या को कम कर सकता है जो उन कार्यों को कह सकते हैं जो अप्रत्यक्ष रूप से उन्हें उत्परिवर्तित करते हैं)।

यहाँ छवि विवरण दर्ज करें

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

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

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

इन जटिल परिदृश्यों में खुद को बचाने का तरीका कोडबेस में उन स्थानों को "टोंटी" करना है जो ऐसे कार्यों को कह सकते हैं जो अंततः इस तरह के सिस्टम के व्यापक दृष्टिकोण से बाहरी दुष्प्रभाव भी पैदा कर सकते हैं जो कच्चे राज्य से परे और इंटरफेस से परे है।

यहाँ छवि विवरण दर्ज करें

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

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

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

राज्य की जटिलता

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

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

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