एक प्रारंभिक विधि होने से बचें


12

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

प्रारंभिक विधि मौजूद क्यों है इसका कारण यह है कि ऑब्जेक्ट वैश्विक दायरे के लिए जल्दी तैयार हो जाता है और फिर प्रारंभिक विधि को एक डीएल को लोड करने के बाद कहा जाता है जिस पर यह निर्भर करता है।

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

एक संभव समाधान कंस्ट्रक्टर में प्रारंभ करें। वैश्विक दायरे में वस्तु के लिए सिर्फ एक संकेतक है। Dll लोड होने के बाद वास्तविक ऑब्जेक्ट बनाएँ।

उपरोक्त समाधान के साथ समस्या जो कोई भी इस वर्ग की वस्तु बनाता है उसे यह जानने की जरूरत है कि इसे केवल डीएल के लोड होने के बाद ही बनाया जाना चाहिए अन्यथा यह विफल हो जाएगा।

क्या यह स्वीकार्य है?


OpenGL से संबंधित वस्तुओं को बनाते समय मुझे यही मुद्दा मिला है, जो OpenGL के संदर्भ में मौजूद होने से पहले तुरंत चालू करने की आवश्यकता होती है, लेकिन OpenGL पर निर्भर ऑब्जेक्ट्स जैसे कि कॉललिस्ट, टेक्सचर, आदि को रखने के लिए माना जाता है

3
मूर्खतापूर्ण प्रश्न # 1: यदि पहले से लोड नहीं किया गया है तो ऑब्जेक्ट कंस्ट्रक्टर DLL को लोड क्यों नहीं कर सकता है?
जॉन आर। स्ट्रोह्म

1
एक पुराने प्रश्न को पुनर्जीवित करने के लिए माफी माँगता हूँ, लेकिन यदि कोई इसे वर्ष 2017 में पढ़ रहा है, तो C ++ 11 में उपयोग करेंcall_once । जो प्रोजेक्ट्स अभी तक C ++ 11 पर नहीं हैं, उन्हें यह अध्ययन करना चाहिए कि C ++ 11 में call_once कैसे लागू किया जाता है (यह किस समस्या को हल करता है, और फिर कैसे) पर ध्यान दें, और फिर C ++ के उनके (बासी) स्वाद में इसे फिर से लागू करें। इसे एक बहु-थ्रेड सुरक्षित सिंक्रनाइज़ेशन आदिम की आवश्यकता होती है, जिसकी अवस्था को वैधानिक रूप से आरंभिक (स्थिर मान के साथ) करने की आवश्यकता होती है। ध्यान दें कि पूर्व-सी ++ 11 संकलक में अन्य idiosyncrasies हो सकते हैं जिन्हें संतुष्ट करने की आवश्यकता है।
'12:55

जवाबों:


7

एक आभासी प्रॉक्सी के लिए एक काम की तरह लगता है।

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

वर्चुअल प्रॉक्सी DLL इनिशियलाइज़ेशन की जाँच करने के लिए ज़िम्मेदार होगा और इसके आधार पर यदि यह निर्णय वास्तविक विषय पर दिया जाना चाहिए।

विकिपीडिया में प्रॉक्सी पैटर्न

आपको यह विचार कैसा लगा?


तुम सच में यहाँ बहुत हल नहीं है। वास्तविक ऑब्जेक्ट में जोड़ी गई प्रत्येक विधि के लिए, आपको उस विधि को प्रॉक्सी में भी जोड़ना होगा। नहीं?

यह init कॉल करने के लिए याद रखने की समस्या से बचा जाता है। फ़ंक्शन, लेकिन ऐसा लगता है कि प्रॉक्सी में प्रत्येक फ़ंक्शन को अभी भी यह देखने के लिए जांचना होगा कि क्या .dll लोड है या नहीं।

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

@edalorzo: जबकि विचार अच्छा है, यहाँ मुद्दा यह है कि हम पहले से ही एक प्रॉक्सी के बारे में बात कर रहे हैं, और ओपी अपने प्रॉक्सी के प्रत्येक तरीके की जाँच करने के बारे में शिकायत कर रहा है ...
मैथ्यू एम।

4

डीएलएल अभी तक लोड नहीं होने पर कुछ भी उपयोगी नहीं होता है; ऑब्जेक्ट केवल एक त्रुटि उत्पन्न करता है। क्या यह एक घातक त्रुटि है? त्रुटि को कैसे नियंत्रित किया जाता है?

क्या आपकी परीक्षण पद्धति यह सुनिश्चित करती है कि तैयार उत्पाद में यह त्रुटि कभी नहीं होती है?

यह परीक्षण के लिए एक नौकरी की तरह लगता है, न कि वास्तुशिल्प डिजाइन के लिए। बस एक त्रुटि वापस मत करो, assertकि यह कभी नहीं होता है।

वर्ग के किसी भी ग्राहक को ठीक करें जो वर्तमान में पकड़ने और त्रुटि की अनदेखी न करें और इसे पहले स्थान पर लाने का कारण बनें।

DLL को लोड करने के बाद एक मल्टीथ्रेडेड पैटर्न एक साझा स्थिति चर सेट करने के लिए हो सकता है, और DLL लोड होने तक ऑब्जेक्ट के कंस्ट्रक्टर प्रतीक्षा (और अन्य थ्रेड्स को ब्लॉक) करें।


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

2

पहली बात: वैश्विक वस्तुओं को कीट से बचें, जब तक कि उनका राज्य कभी नहीं बदलता (कॉन्फ़िगरेशन)।

अब, यदि आप इसके साथ फंस गए हैं, तो किन कारणों से, ऐसे कई डिज़ाइन हैं जो शायद आपकी मदद कर सकते हैं।

मैं दो विचारों के साथ आया:

  1. DLL को लोड करने के लिए एक मुखौटा का उपयोग करें। ऑब्जेक्ट केवल मुखौटा के माध्यम से पहुँचा जा सकता है, मुखौटा निर्माण पर DLL को लोड करता है और एक ही समय में ऑब्जेक्ट को त्वरित करता है।

  2. प्रॉक्सी का उपयोग करें, लेकिन स्मार्ट प्रकार;)

मुझे दूसरे बिंदु पर विस्तार से बताएं , क्योंकि मुझे डर है कि @edalorzo का जवाब आपको भयभीत कर सकता है:

// Private
static Object& GetObjectImpl() { static Object O; return O; }

// Public
static Object& GetObject() {
  Object& o = GetObjectImpl();
  assert(o.isInitialized() && "Object not initialized yet!");
  return o;
}

अब आपके पास केवल एक ही चेक है।

यह कुछ प्रकार के स्मार्ट पॉइंटर के माध्यम से भी किया जा सकता है:

Pointer<Object> o;

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


1

यह एक पेचीदा सवाल है। मुझे लगता है कि वास्तुकला समस्या में मदद कर सकती है।

सबूत से, ऐसा लगता है कि प्रोग्राम लोड होने पर .dll लोड नहीं किया गया है। यह लगभग एक प्लगइन की तरह लगता है।

एक बात जो दिमाग में आती है वह यह है कि आपको .dll को इनिशियलाइज़ करना होगा। प्रोग्रामर को यह मान लेना है कि ऑब्जेक्ट किसी भी तरह से मज़बूती से वापस नहीं आएगा। आप इसका लाभ उठाने में सक्षम हो सकते हैं ( bool isObjectLoaded() { return isInitialized; }), लेकिन आप निश्चित रूप से अपने चेक पर अधिक बग रिपोर्ट प्राप्त कर सकते हैं।

मैं एक सिंगलटन के बारे में सोच रहा था।

यदि आप सिंगलटन को कॉल करते हैं, तो इसे सही ऑब्जेक्ट वापस करना चाहिए यदि यह एक को पुनः प्राप्त कर सकता है। यदि यह सही वस्तु को वापस नहीं कर सकता है, तो आपको कुछ त्रुटि मान / nullptr / खाली आधार वस्तु मिलनी चाहिए। यह काम नहीं करेगा यदि वस्तु आप पर मर सकती है, हालांकि।

इसके अलावा, यदि आपको ऑब्जेक्ट के कई उदाहरणों की आवश्यकता है, तो आप इसके बजाय किसी फैक्ट्री जैसी किसी चीज़ का उपयोग कर सकते हैं।

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