2009-02-27 9 views
5

मुझे राज्य चर के रूप में कमांड बटन के कैप्शन का उपयोग करने के लिए मेरे अंतिम प्रश्न (How to gracefully exit from the middle of a nested subroutine when user cancels?) पर कुछ उचित आलोचनात्मक प्रतिक्रिया मिली। मैंने ऐसा इसलिए किया क्योंकि यह बहुत ही कम कोड के साथ एक बार में दो या तीन उद्देश्यों की सेवा करता है, लेकिन मैं समझता हूं कि यह समस्याएं कैसे पैदा कर सकता है, खासतौर से थोड़ा सा गड़बड़ तरीका जिसे मैंने मूल रूप से प्रस्तुत किया था।वीबी 6 में चर के रूप में बटन कैप्शन का उपयोग करने के बारे में इतना बुरा क्या है?

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

तो यहाँ हम चले:

' Global variables for this form 
Dim DoTheThingCaption(1) As String 
Dim UserCancel, FunctionCompleted As Boolean 

Private Sub Form_Initialize() 
    ' Define the possible captions (is there a #define equivalent for strings?) 
    DoTheThingCaption(0) = "Click to Start Doing the Thing" 
    DoTheThingCaption(1) = "Click to Stop Doing the Thing" 

    ' Set the caption state when form initializes 
    DoTheThing.Caption = DoTheThingCaption(0) 
End Sub 

Private Sub DoTheThing_Click() ' Command Button 

If DoTheThing.Caption = DoTheThingCaption(0) Then 
    UserCancel = False ' this is the first time we've entered this sub 
Else ' We've re-entered this routine (user clicked on button again 
    ' while this routine was already running), so we want to abort 
    UserCancel = True ' Set this so we'll see it when we exit this re-entry 
    DoTheThing.Enabled = False 'Prevent additional clicks 
    Exit Sub 
End If 

' Indicate that we're now Doing the Thing and how to cancel 
DoTheThing.Caption = DoTheThingCaption(1) 

For i = 0 To ReallyBigNumber 
    Call DoSomethingSomewhatTimeConsuming 
    If UserCancel = True Then Exit For ' Exit For Loop if requested 
    DoEvents ' Allows program to see GUI events 
Next 

' We've either finished or been canceled, either way 
' we want to change caption back 
DoTheThing.Caption = DoTheThingCaption(0) 

If UserCancel = True Then GoTo Cleanup 

'If we get to here we've finished successfully 
FunctionCompleted = True 
Exit Sub '******* We exit sub here if we didn't get canceled ******* 

Cleanup: 
'We can only get to here if user canceled before function completed 

FunctionCompleted = False 
UserCancel = False ' clear this so we can reenter later 
DoTheThing.Enabled = True 'Prevent additional clicks 

End Sub '******* We exit sub here if we did get canceled ******* 

तो वहाँ यह है। क्या अभी भी कुछ भी वास्तव में है जो इस तरह से करने के बारे में बुरा है? क्या यह सिर्फ एक शैली मुद्दा है? क्या कोई और चीज है जो मुझे इन चार चीजों को एक और वांछनीय या रखरखाव योग्य तरीके से देगी?

  1. त्वरित जीयूआई राय है कि उपयोगकर्ता के बटन प्रेस कार्रवाई में बदल गया है
  2. स्थान जहां उपयोगकर्ताओं का ध्यान पहले से ही है, तो कार्रवाई उपयोगकर्ताओं के लिए
  3. एक एक बटन रास्ता भी आवश्यक न हो कैसे रद्द करने के लिए कर रहे हैं में त्वरित जीयूआई प्रतिक्रिया शुरू करने के लिए/एक कार्रवाई को रद्द
  4. एक सरल, तत्काल आदेश बटन (जीयूआई पर अव्यवस्था की मात्रा को कम) एक से अधिक पास रोकने के लिए अनुरोध करता है को निष्क्रिय

मैं देख सकता हूँ एक चिंता का विषय हो सकता है टी वह कोड और जीयूआई के बीच युग्मन (कई तरीकों से) बंद कर देता है, इसलिए मैं देख सकता था कि बड़ी परियोजनाओं (या कम से कम बड़े जीयूआई) के लिए यह बड़ी समस्या कैसे हो सकती है। यह एक छोटी परियोजना होती है जहां केवल 2 या 3 बटन होते हैं जो इस तरह के "उपचार" प्राप्त करेंगे।

+0

आईएमओ, यदि आप यूआई को हटाते हैं तो कोड उसी तरह काम करना चाहिए। यह केवल उपयोगकर्ता के साथ बातचीत करने के लिए है। – Deanna

उत्तर

2

मुझे लगता है कि प्रसंस्करण की स्थिति से कैप्शन टेक्स्ट को रद्द करना बेहतर है। इसके अलावा गोटो ने इसे पढ़ना मुश्किल बना दिया है। यहाँ मेरी रिफैक्टर्ड संस्करण ...

Private Const Caption_Start As String = "Click to Start Doing the Thing" 
Private Const Caption_Stop As String = "Click to Stop Doing the Thing" 

Private Enum eStates 
    State_Initialized 
    State_Running 
    State_Canceled 
    State_Completed 
End Enum 

Private Current_State As eStates 

Private Sub Form_Initialize() 

    DoTheThing.Caption = Caption_Start 
    Current_State = State_Initialized 

End Sub 

Private Sub DoTheThing_Click() 

    If Current_State = State_Running Then 

    'currently running - so set state to canceled, reset caption' 
    'and disable button until loop can respond to the cancel' 
    Current_State = State_Canceled 
    DoTheThing.Caption = Caption_Start 
    DoTheThing.Enabled = False 

    Else 

    'not running - so set state and caption' 
    Current_State = State_Running 
    DoTheThing.Caption = Caption_Stop 

    'do the work' 
    For i = 0 To ReallyBigNumber 
     Call DoSomethingSomewhatTimeConsuming 

     'at intervals check the state for cancel' 
     If Current_State = State_Canceled Then 
     're-enable button and bail out of the loop' 
     DoTheThing.Enabled = True 
     Exit For 
     End If 

     DoEvents 

    Next 

    'did we make it to the end without being canceled?' 
    If Current_State <> State_Canceled Then 
     Current_State = State_Completed 
     DoTheThing.Caption = Caption_Start 
    End If 

    End If 

End Sub 
6

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

अब, आपने कमांड बटन टेक्स्ट के लिए अनुमत मानों को परिभाषित करने के लिए पूर्व परिभाषित तारों की एक सरणी पर भरोसा करके कुछ हद तक खतरे को कम कर दिया है। यह कम मुद्दों के एक मुट्ठी भर छोड़ देता है: नहीं-शुरू कर दिया, शुरू कर दिया, पूरा, शुरू कर दिया बल्कि रद्द:

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

"आप बहु-थ्रेडिंग अनुकरण करने के लिए DoEvents का उपयोग कर रहे हैं" - ठीक है * है * VB6 सब के बाद। = पी –

+0

हाँ, वीबी 6 से नफरत करने के कई कारण हैं। – Shog9

+0

मल्टीथ्रेडिंग हार्ड। DoEvents आसान है। – MarkJ

5

इस तरह के [बहुत पुराने) कोड (चर के रूप में बटन कैप्शन] पर काम करते समय सबसे बड़ी समस्या यह है कि वैश्वीकरण एक दुःस्वप्न है .... मुझे पुराने वीबी 6 ऐप का उपयोग करने के लिए स्थानांतरित करना पड़ा अंग्रेजी और जर्मन ... महीनों में नहीं, सप्ताह लग गए।

आप गेटो के साथ भी उपयोग कर रहे हैं ..... कोड को पठनीय बनाने के लिए शायद कुछ रिफैक्टरिंग की आवश्यकता है ??

** टिप्पणियों के जवाब में संपादित करें मैं केवल प्रत्येक proc के शीर्ष पर vb6 में एक गोटो का उपयोग करता हूं; त्रुटि गेटो myErrorHandler पर।

तो प्रो के बहुत नीचे पर मेरे पास एक लाइनर होगा जो त्रुटि को लॉग करने के लिए वैश्विक हैंडलर में गलती करेगा।

+0

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

+0

ओह, मैन ... मुझे यहां दुःस्वप्न फ्लैशबैक मिल रहा है ... कुछ साल पहले लाइब्रेरी पर काम किया था जो माप की इकाइयों का प्रतिनिधित्व करने के लिए तारों का इस्तेमाल करता था - "इन" = इंच, आदि। फिर, किसी बिंदु पर, वे ' एसआई यूओएम के लिए समर्थन में हैक किया गया ... जब मैं इसके साथ किया गया तो lib अपने मूल आकार का 1/10 था ... – Shog9

2

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

मैं तथापि के दो कारण मैं इसे दूसरे तरीके से करना होगा है:

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

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

इसके अलावा, मुझे लगता है कि यह मानना ​​सुरक्षित है कि आपके उदाहरण की आलोचना करने वाले सभी ने ऐसा इसलिए किया क्योंकि उन्होंने किसी बिंदु पर एक समान पसंद किया, और बाद में यह महसूस हुआ कि यह एक गलती थी।

मुझे पता है मैंने किया था।

2

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

1

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

क्या आप ओओपी को समझते हैं?(आलोचना नहीं, बल्कि एक वैध सवाल। यदि आपने किया, तो यह आपके लिए बहुत स्पष्ट होगा। भले ही यह केवल वीबी 6 ओओपी हो।)

5

सामान्य आर्किटेक्चर/युग्मन समस्याओं को अनदेखा करना क्योंकि आप उन मुद्दों से अवगत हैं, आपके दृष्टिकोण के साथ एक समस्या यह है कि जब आप गुण सेट करते हैं तो VB6 नियंत्रण जादू सामग्री करता है। आपको लगता है कि आप केवल एक संपत्ति स्थापित कर रहे हैं लेकिन कई मामलों में आप घटनाओं को भी आग लग रहे हैं। चेकबॉक्स मान को सही पर सेट करने से क्लिक ईवेंट को सक्रिय किया जाता है। टैब नियंत्रण पर टैबिंडेक्स सेट करना एक क्लिक ईवेंट का कारण बनता है। कई मामले हैं।

यदि मुझे सही याद है तो मुझे यह भी लगता है कि यदि आप एक संपत्ति निर्धारित करते हैं, और फिर तुरंत इसे पढ़ते हैं, तो आपको अपडेट दिखाई नहीं देगा। मेरा मानना ​​है कि नया मूल्य देखने से पहले एक स्क्रीन रीफ्रेश होना पड़ता है।

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

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

0

लोकेशन का तर्क लॉजिक ओपी के प्रकार पर सबसे बड़ा असर पड़ रहा है। जैसा कि कई लोगों ने इसका उल्लेख किया - क्या होगा यदि आपको ऐप को चीनी में अनुवाद करने की आवश्यकता है? और जर्मन? और रूसी?

आपको उन भाषाओं को कवर करने वाले अतिरिक्त स्थिरांक भी जोड़ना होगा ... शुद्ध नरक। जीयूआई डेटा एक जीयूआई डेटा, यह क्या होना चाहिए।

विधि ओपी का वर्णन यहां मुझे याद दिलाता है कि हेनरी फोर्ड ने क्या कहा: "किसी भी ग्राहक के पास कोई भी रंग चित्रित हो सकता है जिसे वह काला रंग के रूप में लंबे समय तक चाहता है"।

संबंधित मुद्दे