मैं एक अच्छी पहेली का उतना ही आनंद लेता हूं जितना कि अगले आदमी को। प्रतीत होता है कि यादृच्छिक टुकड़ों के ढेर के साथ शुरू करने और तस्वीर को धीरे-धीरे जीवन लेने के बारे में कुछ संतोषजनक है क्योंकि आप अराजकता को बहाल करते हैं।
हालाँकि, मैंने पहेली करना बंद कर दिया। ओह, शायद अब 13 साल हो गए हैं। मुझे गणित करने दो। मेरे चार बच्चे हैं; सबसे बड़ी उम्र 15 साल है। हां, दो साल की उम्र उस समय के बारे में सही है जब वह एक अधूरी पहेली तक भटकने के लिए पर्याप्त थी, टुकड़ों में से एक के साथ फरार हो गई, और उसे कुत्ते या गर्मी रजिस्टर या शौचालय को खिला दिया।
और अंतिम टुकड़े को एक पहेली में रखना जितना संतोषजनक है, उतना ही यह आत्मा को कुचलने के लिए पहेली में अंतिम टुकड़े को रखने और यह महसूस करने के लिए है कि अंतिम टुकड़ा गायब है।
मैं अपने एरर हैंडलिंग कोड के बारे में ऐसा ही महसूस करता था।
vbWatchdog's Variables इंस्पेक्टर
यदि आप अपनी त्रुटि प्रबंधन (आपको चाहिए) के लिए vbWatchdog का उपयोग करते हैं, तो आपको इसकी सबसे शक्तिशाली विशेषताओं में से एक से परिचित होना चाहिए:चर निरीक्षक। यह ऑब्जेक्ट कॉल स्टैक के प्रत्येक स्तर पर प्रत्येक चर के दायरे में पहुंच प्रदान करता है। जब बग का निवारण करने का समय आता है तो उस स्तर का विवरण डिजिटल सोना होता है।
इन वर्षों में, मैंने एक उन्नत त्रुटि प्रबंधन मॉड्यूल विकसित किया है जो इस सारी जानकारी को लॉग करता है। जैसे ही मैंने अपनी त्रुटि प्रबंधन को ठीक किया, एक दोष बाहर खड़ा होना शुरू हुआ। जबकि मैं अपने अधिकांश चरों के मूल्यों को निकाल सकता था, मैं कभी भी वस्तु चर से बाहर निकल सकता था या तो 'कुछ नहीं' या '{ऑब्जेक्ट}' था।
यह vbWatchdog पर कोई दस्तक नहीं है। वस्तु कुछ भी हो सकती है। यह संभवतः और क्या मूल्य दिखा सकता है? फिर भी, पहेली के इस लापता टुकड़े ने मुझे कुतर दिया। मैं महसूस कर सकता था कि ब्रह्मांड मुझ पर हंस रहा है जब मैं किसी बग का निवारण कर रहा था और इसे हल करने की कुंजी उस पागल शब्द के पीछे छिपी हुई थी, '{ऑब्जेक्ट}'।
यदि मेरे पास उस वस्तु के एक या दो पहचान गुणों को जानने का कोई तरीका होता, तो मैं यह पता लगा सकता था कि वास्तव में क्या चल रहा था।
पहला प्रयास
समस्या को हल करने का मेरा पहला प्रयास हर निराश प्रोग्रामर का टूल है:ब्रूट फोर्स। मेरे वैश्विक त्रुटि हैंडलर में, मैंने एक चुनें...मामला . जोड़ा .TypeDesc
. के इर्द-गिर्द स्टेटमेंट .
उदाहरण के लिए, मेरे पास एक SQL बिल्डर क्लास है जिसे मैं clsSQL . कहता हूं . उस वर्ग के गुणों में से एक है .LastSQL
. उस संपत्ति में अंतिम SQL कथन होता है जिसे वर्ग ने बनाया या निष्पादित किया। यह एक सेलेक्ट स्टेटमेंट या INSERT/UPDATE/DELETE/आदि हो सकता है। (मैंने यह विचार web2py के DAL ऑब्जेक्ट से लिया है। )
मेरे ग्लोबल एरर हैंडलर का एक हिस्सा यहां दिया गया है:
Select Case .TypeDesc
Case "clsSQL"
If Not .Value Is Nothing Then
ThisVar = .Name & ".LastSQL = " & .Value.LastSQL
End If
समय के साथ मैंने इस सूची में अतिरिक्त कस्टम ऑब्जेक्ट प्रकार जोड़ना शुरू किया। प्रत्येक कस्टम प्रकार के साथ, मुझे एक अलग कस्टम प्रॉपर्टी लाने की आवश्यकता होगी।
पहेली के लिए मेरा अंतिम टुकड़ा था। समस्या यह है कि मैंने इसे कुत्ते के पानी के कटोरे में तैरते हुए पाया, सभी एक तरफ चबा रहे थे। मुझे लगता है कि आप कह सकते हैं कि मेरी पहेली पूरी हो गई थी, लेकिन यह एक पायरिक जीत थी।
एक इलाज जो अच्छे से ज्यादा नुकसान करता है
मुझे जल्दी ही एहसास हो गया कि यह समाधान बड़े पैमाने पर नहीं होने वाला है। कई समस्याएं थीं। सबसे पहले, मेरा वैश्विक त्रुटि प्रबंधन कोड फूला हुआ होने वाला था। मैं अपनी कोड लाइब्रेरी के भीतर एक मानक मॉड्यूल में अपना त्रुटि प्रबंधन कोड रखता हूं। इसका मतलब है कि जब भी मैं क्लास मॉड्यूल के लिए समर्थन जोड़ना चाहता था, तो वह कोड मेरी हर एक परियोजना में जुड़ जाएगा। यह सच था, भले ही क्लास मॉड्यूल का उपयोग केवल एक ही प्रोजेक्ट में किया गया हो।
अगली समस्या यह है कि मैं अपने त्रुटि प्रबंधन कोड में बाहरी निर्भरताओं को पेश कर रहा था। क्या होगा यदि मैंने अपना clsSQL . बदल दिया है किसी दिन कक्षा और नाम बदलें या हटा दें .LastSQL
तरीका? जब मैं अपने clsSQL . में काम कर रहा था, तब मुझे इस तरह की निर्भरता का एहसास होने की कितनी संभावनाएं हैं? कक्षा? जब तक मुझे कोई विकल्प नहीं मिल जाता, यह दृष्टिकोण जल्दी ही अपने वजन के नीचे गिर जाएगा।
समाधान के लिए पायथन की तलाश में हैं
मुझे एहसास हुआ कि जो मैं वास्तव में चाहता था वह किसी वस्तु के विहित प्रतिनिधित्व को निर्धारित करने का कोई तरीका था उस वस्तु के भीतर से . मैं इस प्रतिनिधित्व को आवश्यकतानुसार सरल या जटिल रूप से लागू करने में सक्षम होना चाहता था। मैं गारंटी देने का एक तरीका चाहता था कि यह रनटाइम पर नहीं उड़ेगा। मैं चाहता था कि यह हर वर्ग मॉड्यूल के लिए पूरी तरह से वैकल्पिक हो।
यह एक लंबी इच्छा सूची की तरह लगता है, लेकिन मुझे मिले समाधान के साथ मैं उस पर हर वस्तु को संतुष्ट करने में सक्षम था।
एक बार फिर, मैंने पायथन से एक विचार उधार लिया। Python ऑब्जेक्ट्स में एक विशेष गुण होता है जिसे ._repr
. के नाम से जाना जाता है . यह संपत्ति वस्तु का स्ट्रिंग प्रतिनिधित्व है। डिफ़ॉल्ट रूप से, यह ऑब्जेक्ट इंस्टेंस के प्रकार का नाम और स्मृति पता लौटाएगा। हालांकि, पायथन प्रोग्रामर एक .__repr__
को परिभाषित कर सकते हैं डिफ़ॉल्ट व्यवहार को ओवरराइड करने की विधि। मैं अपनी वीबीए कक्षाओं के लिए यही रसदार बिट चाहता था।
मुझे आखिरकार अपना आदर्श समाधान मिल गया। दुर्भाग्य से, मैंने इसे दूसरी भाषा में पाया जहां समाधान वास्तव में भाषा की ही विशेषता है . यह मुझे वीबीए में कैसे मदद करने वाला है? यह पता चला कि विचार महत्वपूर्ण हिस्सा था; मुझे कार्यान्वयन के साथ बस थोड़ा सा रचनात्मक होना था।
बचाव के लिए इंटरफ़ेस
इस पायथन अवधारणा को वीबीए में तस्करी करने के लिए, मैंने भाषा की शायद ही कभी इस्तेमाल की जाने वाली सुविधा की ओर रुख किया:इंटरफेस और टाइपऑफ ऑपरेटर। यहां बताया गया है कि यह कैसे काम करता है।
मैंने एक क्लास मॉड्यूल बनाया है जिसका नाम मैंने iRepresentation . रखा है . अधिकांश भाषाओं में इंटरफेस को कन्वेंशन द्वारा एक अग्रणी "i" के साथ नामित किया गया है। बेशक, आप जो चाहें अपने मॉड्यूल को नाम दे सकते हैं। मेरे iRepresentation . का पूरा कोड यहां दिया गया है कक्षा।
iRepresentation.cls
`--== iRepresentation ==-- class module
Option Compare Database
Option Explicit
Public Property Get Repr() As String
End Property
मुझे यह इंगित करना चाहिए कि क्लास मॉड्यूल के बारे में कुछ खास नहीं है जो वीबीए में इंटरफेस के रूप में कार्य करता है। उसके द्वारा, मेरा मतलब है कि कोई मॉड्यूल स्तर कीवर्ड या छिपी विशेषता नहीं है जिसे हमें सेट करने की आवश्यकता है। हम इस प्रकार का उपयोग करके एक नई वस्तु को तुरंत चालू भी कर सकते हैं, हालांकि बहुत अधिक बिंदु नहीं होगा (एक अपवाद परीक्षण है, लेकिन यह एक अलग दिन के लिए एक विषय है)। उदाहरण के लिए, निम्नलिखित मान्य कोड होंगे:
Dim Representation As iRepresentation
Set Representation = New iRepresentation
Debug.Print Representation.Repr
अब, मान लें कि मेरे पास oJigsawPuzzle . नामक एक कस्टम क्लास मॉड्यूल है . क्लास मॉड्यूल में कई गुण और विधियाँ होती हैं, लेकिन हम एक ऐसा चाहते हैं जो हमें यह पहचानने में मदद करे कि कोई त्रुटि होने पर हम किस आरा पहेली ऑब्जेक्ट से निपट रहे हैं। ऐसी नौकरी के लिए एक स्पष्ट उम्मीदवार एसकेयू है, जो विशिष्ट रूप से पहेली को स्टोर अलमारियों पर एक उत्पाद के रूप में पहचानता है। बेशक, हमारी स्थिति के आधार पर, हम अपने प्रतिनिधित्व में अन्य जानकारी भी शामिल कर सकते हैं।
oJigsawPuzzle.cls
'--== oJigsawPuzzle ==-- class module
Option Compare Database
Option Explicit
Implements iRepresentation ' <-- We need this line...
Private mSKU As String
Private mPieceCount As Long
Private mDesigner As String
Private mTitle As String
Private mHeightInInches As Double
Private mWidthInInches As Double
'... and these three lines
Private Property Get iRepresentation_Repr() As String
iRepresentation_Repr = mSKU
End Property
यह वह जगह है जहां जादू आता है। जब हम वैरिएबल इंस्पेक्टर ऑब्जेक्ट के माध्यम से अपना काम कर रहे होते हैं, तो अब हम यह देखने के लिए प्रत्येक ऑब्जेक्ट वैरिएबल का परीक्षण कर सकते हैं कि क्या यह इस इंटरफ़ेस को लागू करता है। और, अगर ऐसा होता है, तो हम उस मान को पकड़ सकते हैं और इसे अपने बाकी चर मानों के साथ लॉग इन कर सकते हैं।
त्रुटि हैंडलर अंश
' --== Global Error Handler excerpt ==--
'Include Repr property value for classes that
' implement the iRepresentation interface
If TypeOf .Value Is iRepresentation Then
Dim ObjWithRepr As iRepresentation
Set ObjWithRepr = .Value
ThisVar = .Name & ".Repr = " & ObjWithRepr.Repr
End If
और इसके साथ ही, मेरी त्रुटि प्रबंधन पहेली अब पूरी हो गई है। सभी टुकड़ों का हिसाब है। कोई काटने के निशान नहीं हैं। कोई भी टुकड़ा अलग नहीं छील रहा है। कोई रिक्त स्थान नहीं हैं।
मैंने आखिरकार अराजकता को बहाल कर दिया है।