क्या बेहतर है इलीगलस्टैटेसेप्शन या साइलेंट मेथड एक्जीक्यूशन? [बन्द है]


16

मान लीजिए कि मेरे पास MediaPlayer क्लास है जिसमें प्ले () और स्टॉप () तरीके हैं। जब खेल विधि को पहले नहीं बुलाया गया हो तो स्टॉप विधि को लागू करते समय उपयोग करने के लिए सबसे अच्छी रणनीति क्या है। मुझे दो विकल्प दिखाई देते हैं: एक अपवाद को फेंक दें क्योंकि खिलाड़ी उचित स्थिति में नहीं है, या चुपचाप स्टॉप विधि के लिए कॉल की उपेक्षा करें।

जब किसी विधि को किसी स्थिति में नहीं माना जाना चाहिए, तो सामान्य नियम क्या होना चाहिए, लेकिन यह निष्पादन सामान्य रूप से कार्यक्रम को कोई नुकसान नहीं पहुंचाता है?


21
मॉडल व्यवहार के अपवाद का उपयोग न करें जो असाधारण नहीं है।
अलेक्जेंडर - मोनिका

1
अरे! मुझे नहीं लगता कि यह कोई डुप्लिकेट है। मेरा प्रश्न IllegalStateException के बारे में अधिक है और उपरोक्त प्रश्न सामान्य रूप से अपवादों का उपयोग करने के बारे में है।
x2bool

1
केवल चुपचाप असफल होने के बजाय, क्यों नहीं एक चेतावनी के रूप में विसंगति को भी लॉग इन करें? निश्चित रूप से आप जिस जावा का उपयोग कर रहे हैं वह विभिन्न लॉग स्तरों (ERROR, WARN, INFO, DEBUG) का समर्थन करता है।
एरिक सस्टैंडैंड

3
ध्यान दें कि यदि सेट में आइटम पहले से है, तो Set.add कोई अपवाद नहीं फेंकता है। इसका उद्देश्य "यह सुनिश्चित करना है कि तत्व सेट में है", "आइटम को सेट में जोड़ें" के बजाय, इसलिए यह कुछ भी करने से अपने उद्देश्य को प्राप्त करता है यदि तत्व पहले से ही सेट में है।
user253751

2
दिन का शब्द: आलस्य
जूल्स

जवाबों:


37

कोई नियम नहीं है। यह पूरी तरह से है कि आप अपने एपीआई को कैसा महसूस करना चाहते हैं।

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

एक अधिक "मिलनसार" दृष्टिकोण यह स्वीकार करना है कि संक्रमण सबसे अधिक हानिरहित है और इसे अनुमति देकर अपने उपभोगकर्ता डेवलपर्स के प्रति दयालु बनें।

इसलिए, अगर यह मेरे ऊपर था, तो मैं अपवाद को छोड़ दूंगा।


15
यह उत्तर हमें याद दिलाता है कि कभी-कभी साधारण बातचीत के लिए भी राज्य के बदलावों को रेखांकित करना एक अच्छा विचार है।

6
इसे ध्यान में रखते हुए, एक अपवाद को फेंकना पांडित्यपूर्ण और अनुचित होगा। यह एपीआई को स्कूल बस में कष्टप्रद बच्चे से बात करने के सामाजिक समकक्ष की तरह महसूस करेगा। > अपवाद आपको दंडित करने के लिए डिज़ाइन नहीं किए गए हैं: वे आपको यह बताने के लिए डिज़ाइन किए गए हैं कि कुछ अप्रत्याशित हुआ है। मैं व्यक्तिगत रूप से एक विधि के लिए बहुत आभारी रहूंगा MediaPlayer.stop()जिसने IllegalStateExceptionडिबगिंग कोड के घंटे खर्च करने के बजाय फेंक दिया और सोच रहा था कि नर्क "कुछ भी नहीं होता" (यानी "यह सिर्फ काम नहीं करता है")।
इरेटलिंगलिंगिस्ट

3
बेशक, अगर आपका डिज़ाइन कहता है कि लूपबैक संक्रमण अमान्य है, तो हाँ आपको अपवाद छोड़ देना चाहिए। हालांकि, मेरा जवाब एक डिजाइन के बारे में था जहां संक्रमण पूरी तरह से ठीक है।
मेटाफ़ाइट

1
StopOrThrow()भयानक लगता है। यदि आप उस गली से नीचे जा रहे हैं तो मानक पैटर्न का उपयोग क्यों न करें TryStop()? इसके अलावा, आम तौर पर, जब एक एपीआई का व्यवहार स्पष्ट नहीं होता है (जैसा कि उनमें से अधिकांश हैं) डेवलपर्स से केवल अनुमान या प्रयोग करने की उम्मीद नहीं की जाती है, वे प्रलेखन को देखने की उम्मीद करते हैं। इसलिए मुझे MSDN बहुत पसंद है।
मेटाफ़ाइट

1
व्यक्तिगत रूप से मैं असफल-तेज विकल्प पसंद करता हूं, इसलिए मैं एपीआई के उपयोगकर्ता को इंगित करने के लिए अवैध विरोधाभास के लिए जाऊंगा कि उसके तर्क में कुछ गलत है, भले ही वह हानिरहित हो। मैं अक्सर अपने आप को अपने कोड से उन अपवादों को प्राप्त करता हूं, वास्तव में यह पता लगाने में सहायक है कि मेरा अनफिनिश्ड काम पहले से ही गलत है
वालफ्रैट

17

क्रिया के दो अलग-अलग प्रकार हैं जिन्हें करने की इच्छा हो सकती है:

  1. इसके साथ ही परीक्षण करें कि कुछ एक राज्य में है, और इसे दूसरे में बदल दें।

  2. पिछले राज्य के लिए बिना किसी विशेष राज्य के लिए कुछ सेट करें।

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

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


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

एक bool TryStop()और void Stop()कोड उदाहरण यह वास्तव में उत्कृष्ट उत्तर देगा।
RubberDuck

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

1
तब मैं अपने जवाब @supercat गलत समझा गया है
RubberDuck

2
मैं यह बताना चाहता हूं कि इस तरह से परीक्षण करना और स्थापित करना लोकतंत्र के कानून का उल्लंघन नहीं है, बशर्ते एपीआई भी इसे बदले बिना प्लेबैक राज्य का परीक्षण करने का एक तरीका प्रदान करता है। यह एक पूरी तरह से अलग विधि हो सकती है, कहते हैं isPlaying()
candied_orange

11

कोई सामान्य नियम नहीं है। इस विशिष्ट मामले में, आपके API के उपयोगकर्ता का इरादा खिलाड़ी को मीडिया चलाने से रोकना है। यदि खिलाड़ी मीडिया नहीं खेल रहा है, MediaPlayer.stop()तो कुछ भी नहीं कर सकता है और विधि कॉलर का लक्ष्य अभी भी प्राप्त किया जाएगा - मीडिया नहीं खेल रहा है।

एक अपवाद को फेंकने के लिए एपीआई के उपयोगकर्ता को यह देखने की आवश्यकता होगी कि क्या खिलाड़ी वर्तमान में खेल रहा है या अपवाद को पकड़ या संभाल रहा है। यह एपीआई का उपयोग करने के लिए एक अधिक काम कर देगा।


11

अपवादों का उद्देश्य यह संकेत देना नहीं है कि कुछ बुरा हुआ है; यह संकेत है कि

  1. कुछ बुरा हुआ है
  2. मुझे नहीं पता कि यहाँ कैसे ठीक किया जाए
  3. कॉल करने वाले, या इससे मिलने वाले कॉलस्टैक से कुछ पता होना चाहिए कि कैसे निपटना है
  4. इसलिए मैं नुकसान या डेटा भ्रष्टाचार को रोकने के लिए वर्तमान कोड पथ के निष्पादन को रोक रहा हूं, और सफाई करने के लिए फोन करने वाले को छोड़ रहा हूं।

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

इसलिए, आपको इस स्थिति में अपवाद नहीं फेंकना चाहिए।


+1। यह पहला उत्तर है जो दिखाता है कि अपवाद यहां उचित क्यों नहीं है। अपवाद संकेत देते हैं कि कॉलर को असाधारण मामले के बारे में जानने की आवश्यकता है। इस मामले में, लगभग निश्चित रूप से प्रश्न में वर्ग के ग्राहक परवाह नहीं करेंगे कि क्या 'स्टॉप ()' कॉलिंग वास्तव में एक राज्य संक्रमण का कारण बना, इसलिए संभवतः एक अपवाद के बारे में जानना नहीं चाहेंगे।
जूल्स

5

इसे इस तरह देखो:

यदि क्लाइंट खिलाड़ी को नहीं खेल रहा है, तो स्टॉप () को कॉल करता है, तो स्टॉप () स्वचालित रूप से सफल होता है क्योंकि खिलाड़ी वर्तमान में बंद अवस्था में है।


3

नियम यह है कि आपकी विधि के अनुबंध की आवश्यकता है।

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

वहाँ किसी भी कारण से भी आपको होगा चाहते हैं एक अपवाद फेंकने के लिए? यदि उपयोगकर्ता कोड अंत में इस तरह दिखाई देगा:

try {
    player.stop();
} catch(IllegalStateException e) {
    // do nothing, player was already stopped
}

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

यह खिलाड़ी देखने योग्य हो सकता है, और पहले से ही कुछ चीजों के बारे में पर्यवेक्षकों को सूचित कर सकता है - जैसे कि जब यह playingकरने के stoppingलिए पारगमन से पर्यवेक्षकों को सूचित करता है stopped। इस मामले में, विधि को अपवाद के रूप में फेंकना आवश्यक नहीं है। कॉलिंग stopसिर्फ कुछ नहीं करेगा यदि खिलाड़ी पहले से ही रोक दिया गया है, और जब इसे रोका नहीं जाता है तो यह पर्यवेक्षकों को संक्रमण के बारे में सूचित करेगा।

सभी में, यह इस बात पर निर्भर करता है कि आपका तर्क कहां समाप्त होगा। लेकिन मुझे लगता है कि इसके बाद अपवाद को फेंकना बेहतर डिजाइन विकल्प हैं।

यदि कॉलर को हस्तक्षेप करना पड़े तो आपको एक अपवाद फेंक देना चाहिए । इस मामले में उसे नहीं करना है, आप खिलाड़ी को बस वैसे ही रहने दे सकते हैं जैसे यह काम करना जारी रखता है।


3

एक सामान्य सामान्य रणनीति है जो आपको यह निर्णय लेने में मदद करती है।

विचार करें कि यदि इसे फेंक दिया जाना था तो अपवाद को कैसे संभाला जाएगा।

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

इसका मतलब है कि अपवाद को पकड़ने और कहीं निगलने की आवश्यकता होगी। और इसका मतलब है कि आप अपवाद को पहले स्थान पर नहीं फेंक रहे हैं क्योंकि आप एक अलग कार्रवाई नहीं करना चाहते हैं

यह केवल अपवादों पर लागू नहीं होता है, लेकिन किसी भी तरह की शाखाओं में बँटते हैं: मूल रूप से अगर व्यवहार में कोई भी अंतर नहीं होना चाहिए, तो शाखा-विभाजन की कोई आवश्यकता नहीं है।

उस ने कहा, "या" सफल "" यह संकेत देते हुए कि stop()वापसी का booleanसंकेत देने के लिए अपने तरीके को परिभाषित करने में बहुत नुकसान नहीं है । आप शायद कभी इसका उपयोग नहीं करेंगे, लेकिन एक वापसी मूल्य अधिक आसानी से और स्वाभाविक रूप से एक अपवाद की तुलना में अनदेखा किया जा सकता है।


2

यहाँ बताया गया है कि android कैसे करता है: MediaPlayer

संक्षेप में, stopजब startकॉल नहीं किया गया है तो कोई समस्या नहीं है, सिस्टम रुकने की स्थिति में रहता है, लेकिन अगर उस खिलाड़ी को कॉल किया जाए जो यह भी नहीं जानता है कि वह क्या खेल रहा है, तो एक अपवाद फेंक दिया जाता है, क्योंकि कॉल करने का कोई अच्छा कारण नहीं है वहां रुक जाओ।


1

जब किसी विधि को किसी स्थिति में नहीं माना जाना चाहिए, तो सामान्य नियम क्या होना चाहिए, लेकिन यह निष्पादन सामान्य रूप से कार्यक्रम को कोई नुकसान नहीं पहुंचाता है?

मैं देखता हूं कि आपके कथन में एक मामूली विरोधाभास क्या हो सकता है जो आपके लिए उत्तर को स्पष्ट कर सकता है। ऐसा क्यों है कि विधि को बुलाया नहीं जाता है और फिर भी इसका निष्पादन नहीं होता है ?

क्यों विधि "नहीं माना जाता है" कहा जाता है? यह एक आत्म-लगाया प्रतिबंध की तरह लगता है। यदि आपके एपीआई में कोई "नुकसान" या प्रभाव नहीं है, तो कोई अपवाद नहीं है। यदि विधि को वास्तव में नहीं कहा जाना चाहिए क्योंकि यह अमान्य या अप्रत्याशित स्थिति बना सकता है, तो एक अपवाद फेंक दिया जाना चाहिए।

उदाहरण के लिए अगर मैं एक डीवीडी प्लेयर के लिए चला गया और "स्टार्ट" मारने से पहले "स्टॉप" मारा और यह दुर्घटनाग्रस्त हो गया, तो इससे मुझे कोई मतलब नहीं होगा। इसे बस वहां बैठना चाहिए या इससे भी बदतर स्थिति, स्क्रीन पर "रोक" को स्वीकार करना चाहिए। एक त्रुटि कष्टप्रद होगी और किसी भी तरह से सहायक नहीं होगी।

हालांकि, क्या मैं अलार्म कोड में इसे "बंद" करने के लिए डाल सकता हूं जब यह पहले से ही बंद है (विधि को कॉल कर रहा है), जो इसे एक राज्य में प्रवेश करने का कारण बन सकता है जो इसे बाद में ठीक से उत्पन्न होने से रोक देगा? यदि ऐसा है, तो तकनीकी रूप से, हालांकि, "कोई नुकसान नहीं हुआ", हालांकि बाद में समस्या हो सकती है, एक त्रुटि फेंक दें। मैं इसके बारे में जानना चाहूंगा, भले ही यह वास्तव में उस राज्य में नहीं गया हो। बस संभावना काफी है। यह एक होगा IllegalStateException

आपके मामले में, यदि आपकी राज्य मशीन अमान्य / अनावश्यक कॉल को संभाल सकती है, तो इसे अनदेखा करें, अन्यथा एक त्रुटि फेंक दें।

संपादित करें:

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


इसे कहा नहीं जाना चाहिए क्योंकि इसे कॉल करना कॉलगर्ल में बग को दर्शाता है।
user253751

@ मिनीबिस: जरूरी नहीं। उदाहरण के लिए, वह कॉलर कुछ UI बटन का ऑन-क्लिक श्रोता हो सकता है। (एक उपयोगकर्ता के रूप में, आप शायद एक त्रुटि संदेश पसंद नहीं करेंगे यदि आप गलती से मीडिया को रोकने पर स्टॉप बटन पर क्लिक करते हैं।)
मेरिटॉन

@meriton यदि यह UI बटन का ऑन-क्लिक श्रोता था, तो उत्तर स्पष्ट होगा - "यदि बटन दबाया जाए तो आप जो करना चाहते हैं वह करें"। स्पष्ट रूप से यह नहीं है, यह अनुप्रयोग के लिए कुछ आंतरिक है।
user253751

@ मिनीबिस - मैंने अपनी प्रतिक्रिया संपादित की। मुझे उम्मीद है यह मदद करेगा।
जिम

1

वास्तव में क्या करना MediaPlayer.play()है और MediaPlayer.stop()क्या करना? - वे कर रहे हैं घटना उपयोगकर्ता इनपुट के लिए श्रोताओं वे वास्तव में तरीकों जो किसी प्रकार शुरू की मीडिया सिस्टम पर स्ट्रीम या कर रहे हैं? यदि वे सभी उपयोगकर्ता इनपुट के लिए श्रोता हैं, तो यह उनके लिए कुछ भी नहीं करने के लिए पूरी तरह से उचित है (हालांकि यह कम से कम उन्हें कहीं लॉग करने के लिए एक अच्छा विचार होगा)। हालाँकि, यदि वे उस मॉडल को प्रभावित करते हैं जिसे आपका UI नियंत्रित कर रहा है, तो वे फेंक सकते हैं IllegalStateExceptionक्योंकि खिलाड़ी को किसी प्रकार का isPlaying=trueया isPlaying=falseराज्य होना चाहिए (इसे यहां लिखे गए वास्तविक बूलियन ध्वज की आवश्यकता नहीं है), और इसलिए जब आप कॉल MediaPlayer.stop()करते हैं isPlaying=false, तो विधि वास्तव में "रोक" नहीं सकती है MediaPlayerक्योंकि ऑब्जेक्ट को बंद करने के लिए उपयुक्त स्थिति में नहीं है - का विवरण देखेंjava.lang.IllegalStateException वर्ग:

संकेत है कि एक विधि अवैध या अनुचित समय पर लागू किया गया है। दूसरे शब्दों में, जावा वातावरण या जावा एप्लिकेशन अनुरोधित ऑपरेशन के लिए उपयुक्त स्थिति में नहीं है।

अपवाद क्यों फेंकना अच्छा हो सकता है

बहुत सारे लोगों को लगता है कि अपवाद सामान्य रूप से खराब हैं, क्योंकि उन्हें कभी भी फेंकना नहीं चाहिए (cf. Joel on Software )। हालाँकि, कहते हैं कि आपके पास एक MediaPlayerGUI.notifyPlayButton()कॉल है MediaPlayer.play(), और MediaPlayer.play()अन्य कोड का एक गुच्छा आमंत्रित करता है और कहीं-कहीं लाइन के नीचे यह जैसे कि PulseAudio के साथ इंटरफेस करता है , लेकिन मुझे (डेवलपर) पता नहीं है क्योंकि मैंने वह सभी कोड नहीं लिखा था।

फिर, एक दिन कोड पर काम करते समय, मैं "प्ले" पर क्लिक करता हूं और कुछ भी नहीं होता है। यदि MediaPlayerGUIController.notifyPlayButton()कुछ लॉग करता है, तो कम से कम मैं लॉग में देख सकता हूं और जांच सकता हूं कि बटन क्लिक वास्तव में पंजीकृत था ... लेकिन यह क्यों नहीं चलता है? ठीक है, कहते हैं कि वास्तव में पल्सआडियो रैपर के साथ कुछ गड़बड़ है जो MediaPlayer.play()आह्वान करता है। मैं फिर से "प्ले" बटन पर क्लिक करता हूं, और इस बार मुझे एक IllegalStateException:

 Exception in thread "main" java.lang.IllegalStateException: MediaPlayer already in play state.

     at org.superdupermediaplayer.MediaPlayer.play(MediaPlayer.java:16)
     at org.superdupermediaplayer.gui.MediaPlayerGUIController.notifyPlayButton(MediaPlayerGUIController.java:25)
     at org.superdupermediaplayer.gui.MediaPlayerGUI.main(MediaPlayerGUI.java:14)

उस स्टैक ट्रेस को देखकर, मैं MediaPlayer.play()डिबगिंग करने से पहले सब कुछ अनदेखा कर सकता हूं और अपना समय बिता सकता हूं, जैसे कि ऑडियो स्ट्रीम शुरू करने के लिए पल्सएडियो को कोई संदेश क्यों नहीं दिया जा रहा है।

दूसरी ओर, यदि आप एक अपवाद नहीं फेंकते हैं, तो मेरे पास अन्य के साथ काम शुरू करने के लिए कुछ भी नहीं है: "बेवकूफ कार्यक्रम कोई संगीत नहीं बजाता है"; यद्यपि यह स्पष्ट नहीं है कि स्पष्ट त्रुटि छिपाना जैसे वास्तव में एक अपवाद को निगलना जो वास्तव में फेंक दिया गया था , आप अभी भी संभावित रूप से दूसरों का समय बर्बाद कर रहे हैं जब कुछ गलत होता है ... तो अच्छा हो और उन पर एक अपवाद फेंक दें।


0

मैं एपीआई को इस तरह से डिजाइन करना पसंद करता हूं जिससे उपभोक्ता के लिए गलतियां करना मुश्किल या असंभव हो। उदाहरण के लिए, होने MediaPlayer.play()और होने के बजाय MediaPlayer.stop(), आप MediaPlayer.playToggle()"रोका" और "खेल" के बीच कौन से टॉगल कर सकते हैं । इस तरह, विधि हमेशा कॉल करने के लिए सुरक्षित है - अवैध राज्य में जाने का कोई जोखिम नहीं है।

बेशक, यह हमेशा संभव या आसान नहीं होता है। आपके द्वारा दिया गया उदाहरण एक तत्व को हटाने की कोशिश करने के लिए तुलनीय है जो पहले से ही सूची से हटा दिया गया था। आप या तो हो सकते हैं

  • इसके बारे में व्यावहारिक और कोई त्रुटि नहीं है। यह निश्चित रूप से बहुत सारे कोड को सरल करता है, जैसे, if (list.contains(x)) { list.remove(x) }आपको केवल लिखने की आवश्यकता होने के बजाय list.remove(x))। लेकिन, यह बग को छिपा भी सकता है।
  • या आप पांडित्यपूर्ण हो सकते हैं और एक त्रुटि का संकेत दे सकते हैं कि सूची में वह तत्व नहीं है। कोड कई बार और अधिक जटिल हो सकता है, क्योंकि आपको लगातार यह सत्यापित करना होगा कि विधि को कॉल करने से पहले पूर्व-शर्तें संतुष्ट हैं, लेकिन उल्टा यह है कि अंतिम बग को ट्रैक करना आसान है।

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


3
मैं playToggle()उपयोग करने में आसान होने के बारे में असहमत हूं : वांछित प्रभाव प्राप्त करने के लिए (खिलाड़ी खेल रहा है या नहीं खेल रहा है), आपको इसकी वर्तमान स्थिति जानना आवश्यक होगा। इसलिए, यदि आपको उपयोगकर्ता इनपुट मिलता है, तो आपको खिलाड़ी को रोकने का अनुरोध करना होगा, आपको पहले यह जांचना होगा कि क्या खिलाड़ी वर्तमान में खेल रहा है, तो उत्तर के आधार पर उसके राज्य को टॉगल करें या नहीं। यह सिर्फ एक stop()पद्धति को कॉल करने की तुलना में बहुत अधिक बोझिल है और इसके साथ किया जाता है।
विस्फ़ोटक -

वैसे मैंने कभी नहीं कहा कि इसका उपयोग करना आसान था - मेरा दावा था कि यह सुरक्षित है। इसके अलावा, आपका उदाहरण मानता है कि उपयोगकर्ता को अलग-अलग स्टॉप और प्ले बटन दिए जाएंगे। अगर वास्तव में ऐसा होता तो हाँ, playToggleउपयोग करने के लिए बहुत ही बोझिल होगा। लेकिन अगर उपयोगकर्ता को इसके बजाय टॉगल बटन भी दिया गया था, तो playToggleप्ले / स्टॉप की तुलना में उपयोग करना आसान होगा।
पेड्रो रॉड्रिक्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.