2008-08-25 15 views
11

मुझे अपवाद हैंडलिंग के दो दृष्टिकोण पता हैं, चलिए उन्हें देखें।अपवाद हैंडलिंग: अनुबंध बनाम असाधारण दृष्टिकोण

  1. अनुबंध दृष्टिकोण।

    जब कोई विधि ऐसा नहीं करती है जो यह कहती है कि यह विधि शीर्षलेख में करेगी, तो यह अपवाद फेंक देगा। इस प्रकार विधि "वादा करता है" कि यह ऑपरेशन करेगा, और यदि यह किसी कारण से विफल रहता है, तो यह अपवाद फेंक देगा।

  2. असाधारण दृष्टिकोण।

    कुछ अजीब होता है जब केवल अपवाद फेंक देते हैं। जब आप सामान्य नियंत्रण प्रवाह (यदि कथन) के साथ स्थिति को हल कर सकते हैं तो आपको अपवादों का उपयोग नहीं करना चाहिए। आप नियंत्रण प्रवाह के लिए अपवादों का उपयोग नहीं करते हैं, जैसा कि आप अनुबंध दृष्टिकोण में हो सकते हैं।

    हम एक ग्राहक वर्ग के लिए एक विधि OrderProduct कहा जाता है कि है:

अलग मामलों में दोनों तरीकों का उपयोग करने देता है।

अनुबंध दृष्टिकोण:

class Customer 
{ 
    public void OrderProduct(Product product) 
    { 
      if((m_credit - product.Price) < 0) 
        throw new NoCreditException("Not enough credit!"); 
      // do stuff 
    } 
} 

असाधारण दृष्टिकोण:

class Customer 
{ 
    public bool OrderProduct(Product product) 
    { 
      if((m_credit - product.Price) < 0) 
        return false; 
      // do stuff 
      return true; 
    } 
} 

if !(customer.OrderProduct(product)) 
      Console.WriteLine("Not enough credit!"); 
else 
    // go on with your life 

यहाँ मैं, असाधारण दृष्टिकोण पसंद करते हैं के रूप में यह वास्तव में असाधारण एक ग्राहक के पास पैसे नहीं यह सोचते हैं कि वह लॉटरी जीत नहीं पाए है कि नहीं है ।

लेकिन यहां एक ऐसी स्थिति है जो मैं अनुबंध शैली पर गलती करता हूं।

असाधारण:

class CarController 
{ 
    // returns null if car creation failed. 
    public Car CreateCar(string model) 
    { 
     // something went wrong, wrong model 
     return null; 
    } 
} 

जब मैं एक विधि CreateCar कहा जाता है कहते हैं, मैं बहुत कुछ घटिया नल पॉइंटर है, जो मेरे चल कोड एक दर्जन से अधिक लाइनों बाद में विनाश कर सकते हैं के बजाय एक कार उदाहरण उम्मीद wel। इस प्रकार मैं इस से अनुबंध पसंद करता हूं:

class CarController 
{ 

    public Car CreateCar(string model) 
    { 
     // something went wrong, wrong model 
     throw new CarModelNotKnownException("Model unkown"); 

     return new Car(); 
    } 
} 

आप किस शैली का उपयोग करते हैं? अपवादों के लिए सबसे अच्छा सामान्य दृष्टिकोण आपको क्या लगता है?

उत्तर

7

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

+0

+1 एक शून्य या -1 परिणाम लौटने के आपके उदाहरण के लिए +1। कोड को स्पष्ट करने के बजाय, शून्य या -1 वापसी आवेदक विधि के लेखक को यह जानने के लिए मजबूर करती है कि कैसे लागू विधि गैर-मानक परिणाम की रिपोर्ट करने का विकल्प चुनती है। अपवाद एक क्लीनर, अनुबंध दृष्टिकोण है जिसमें आवेदक (संभवतः) बदलते काले बॉक्स के रूप में आवेदक का इलाज कर सकता है। सभी आवेदकों को यह पता होना चाहिए कि इसे अपवाद को संभालना होगा, न कि यह आज एक शून्य है और एक Integer.MIN_VALUE कल है। – rajah9

0

मेरा मानना ​​है कि यदि आप एक कक्षा का निर्माण कर रहे हैं जिसका उपयोग बाहरी कार्यक्रम (या अन्य कार्यक्रमों द्वारा पुन: उपयोग किया जाएगा) तो आपको अनुबंध दृष्टिकोण का उपयोग करना चाहिए। इसका एक अच्छा उदाहरण किसी भी प्रकार का एपीआई है।

1

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

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

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

0

यदि आप वास्तव में अपवादों में रुचि रखते हैं और मजबूत सिस्टम बनाने के लिए उनका उपयोग कैसे करें, इस बारे में सोचना चाहते हैं, तो Making reliable distributed systems in the presence of software errors पढ़ने पर विचार करें।

0

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

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

 
TValue GetValue(TKey Key); 
bool TryGetValue(TKey Key, ref TValue value); 

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

 
// In case of failure, set ok false and return default<TValue>. 
TValue TryGetResult(ref bool ok, TParam param); 
// In case of failure, indicate particular problem in GetKeyErrorInfo 
// and return default<TValue>. 
TValue TryGetResult(ref GetKeyErrorInfo errorInfo, ref TParam param); 

नोट ऐसा ही कुछ का उपयोग कर एक इंटरफ़ेस के भीतर सामान्य TryGetResult पैटर्न परिणाम प्रकार के संबंध में इंटरफ़ेस invariant बना देगा; उपरोक्त पैटर्न में से एक का उपयोग करके परिणाम प्रकार के संबंध में इंटरफ़ेस को कॉन्वर्सेंट होने की अनुमति मिल जाएगी।

 
    var myThingResult = myThing.TryGetSomeValue(ref ok, whatever); 
    if (ok) { do_whatever } 

नहीं काफी मानक दृष्टिकोण है, लेकिन कुछ मामलों में लाभ यह औचित्य साबित हो सकता है: इसके अलावा, यह परिणाम एक 'var' घोषणा में इस्तेमाल किया जा करने की अनुमति देगा।

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