कुछ भी नहीं है कि उत्परिवर्ती अंततः राज्य में हेरफेर करता है?
हां, लेकिन अगर यह एक छोटे वर्ग के सदस्य के पीछे है जो पूरे सिस्टम में एकमात्र इकाई है जो अपने निजी राज्य में हेरफेर कर सकता है, तो उस राज्य में बहुत संकीर्ण गुंजाइश है।
जितना संभव हो उतना कम राज्य से निपटने के लिए आपके पास क्या होना चाहिए?
चर के दृष्टिकोण से: कोड की कुछ पंक्तियों को संभव के रूप में उपयोग करने में सक्षम होना चाहिए। चर के दायरे को न्यूनतम तक सीमित करें।
कोड के दृष्टिकोण की रेखा से: कोड की उस पंक्ति से कुछ चर संभव हो सकते हैं। चर की संख्या सीमित करें कि कोड पंक्ति कर सकते हैं संभवतः एक्सेस (यह भी है कि ज्यादा फर्क नहीं पड़ता कि यह करता है यह उपयोग, कि सभी मामलों है कि क्या यह है सकते हैं )।
वैश्विक चर बहुत खराब हैं क्योंकि उनके पास अधिकतम गुंजाइश है। भले ही वे कोडबेस के कोड से 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 मिलियन लाइनों को फैलाता है, लेकिन यह आपके सॉफ़्टवेयर की शुद्धता के बारे में तर्क करने में बहुत मदद कर सकता है, और यह पता लगाता है कि आपके परिवर्तन अनुमानित परिणाम प्राप्त करते हैं, जब आप संख्या को काफी सीमित करते हैं / बाधा डालते हैं। उन स्थानों के बारे में जो महत्वपूर्ण स्थिति को बदल सकते हैं कि पूरी वास्तुकला सही ढंग से कार्य करने के लिए घूमती है।
कच्चे चर से परे बाहरी साइड इफेक्ट्स होते हैं, और बाहरी साइड इफेक्ट्स एक त्रुटि का स्रोत होते हैं, भले ही वे मुट्ठी भर सदस्य कार्यों तक ही सीमित हों। यदि फ़ंक्शंस का एक बोट लोड सीधे उन सदस्य फ़ंक्शंस को कॉल कर सकता है, तो सिस्टम में फ़ंक्शंस का एक बोटलोड है जो अप्रत्यक्ष रूप से बाहरी दुष्प्रभावों का कारण बन सकता है, और यह जटिलता बढ़ाता है। यदि कोडबेस में केवल एक ही स्थान है, जो उन सदस्य कार्यों तक पहुंच रखता है, और निष्पादन का एक मार्ग सभी जगहों पर छिटपुट घटनाओं से उत्पन्न नहीं होता है, लेकिन इसके बजाय एक बहुत ही नियंत्रित, पूर्वानुमानित फैशन में निष्पादित किया जाता है, तो यह जटिलता है।
राज्य की जटिलता
यहां तक कि राज्य की जटिलता को ध्यान में रखना एक महत्वपूर्ण कारक है। एक सरल संरचना, एक सार इंटरफेस के पीछे व्यापक रूप से सुलभ, गड़बड़ करने के लिए इतना मुश्किल नहीं है।
एक जटिल ग्राफ डेटा संरचना जो एक जटिल वास्तुकला के मूल तार्किक प्रतिनिधित्व का प्रतिनिधित्व करती है, गड़बड़ करना बहुत आसान है, और एक तरह से जो ग्राफ़ के अपरिवर्तनों का उल्लंघन भी नहीं करता है। एक सरल संरचना की तुलना में एक ग्राफ कई गुना अधिक जटिल होता है, और इसलिए कोडबेस की कथित जटिलता को कम करने के लिए ऐसे मामले में यह और भी महत्वपूर्ण हो जाता है कि इस तरह की ग्राफ संरचना की पूर्ण न्यूनतम तक पहुंच रखने के लिए, और जहां उस तरह की "सेंट्रल अपडैटर" रणनीति है जो छिटपुट से बचने के लिए एक पुल प्रतिमान को निष्क्रिय करता है, प्रत्यक्ष रूप से सभी जगह से ग्राफ डेटा संरचना को सीधा धक्का देता है।