2009-08-29 29 views
8

मेरे पास इस प्रकार का प्रारूपत्रुटि हैंडलिंग क्या मुझे अपवाद फेंकना चाहिए? या स्रोत पर संभाल लें?

एएसपीनेट एमवीसी व्यू -> सेवा परत -> रिपोजिटरी है।

तो दृश्य सेवा परत जो उस में व्यापार/मान्यता तर्क है जो बारी-बारी भंडार कॉल कहते हैं।

अब मेरी सेवा परत विधि आम तौर पर एक bool वापसी प्रकार इतना है कि मैं सच लौटा सकते हैं या डेटाबेस क्वेरी अच्छा के माध्यम से चला गया है। या अगर यह असफल रहा। फिर उपयोगकर्ता को एक सामान्य संदेश दिखाया जाता है।

मैं निश्चित रूप से elmah के साथ त्रुटि लॉग इन करूंगा। हालांकि मुझे यकीन नहीं है कि मुझे इस बिंदु पर कैसे जाना चाहिए।

अभी इसी तरह मेरी रिपोजिटरी में अद्यतन, निर्माण, हटाने के लिए शून्य वापसी प्रकार हैं।

तो कहें कि क्या कोई अपडेट विफल रहता है, क्या मुझे अपने भंडार में कोशिश/पकड़ना चाहिए जो त्रुटि को फेंकता है, फिर मेरी सेवा परत इसे पकड़ती है और एल्मा सिग्नलिंग करती है और झूठी वापसी करती है?

या मेरे पास इन रिपोजिटरी विधियों को "बूल" वापस करना चाहिए, रिपॉजिटरी में त्रुटि को आज़माएं/पकड़ें और फिर सेवा परत पर "सत्य" या "झूठी" लौटाएं जो बदले में "सत्य" या "झूठी" देखने के लिए?

अपवाद संचालन अभी भी मुझे confuses त्रुटियों जब जब त्रुटि को पकड़ने के लिए फेंक और कैसे संभाल और।

उत्तर

15

अंगूठे का नियम मैं हमेशा का उपयोग करें:

इन दो एपीआई पर विचार करें

  • निम्न स्तर पर, फेंक जब एक ऑपरेशन असाधारण परिस्थितियों के कारण पूरी नहीं कर सकते हैं।
  • मध्यम परतों में, एकाधिक अपवाद प्रकारों को पकड़ें और एक अपवाद प्रकार में पुनः लिखें।
  • अंतिम जिम्मेदार पल में अपवादों को संभालें।
  • दस्तावेज़!

    1. उपयोगकर्ता क्लिक सबमिट बटन:

यहाँ एक बहु परत ASP.NET MVC अनुप्रयोग (यूआई, नियंत्रक, तर्क, सुरक्षा, भंडार) के लिए स्यूडोकोड में एक उदाहरण है।

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

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


    वैसे, कुछ भी नहीं कहना है यदि आप ऐसा नहीं कर सकते हैं:

    try 
    { 
        var result = DoSomethingOhMyWhatIsTheReturnType(); 
    } 
    catch(LogicException e) 
    { 
        if(e.InnerException is SqlException) 
        { 
        // handle sql exceptions 
        }else if(e.InnerException is InvalidCastException) 
        { 
        // handle cast exceptions 
        } 
        // blah blah blah 
    } 
    
    +1

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

    +0

    1) बाव। आपको इन नए अपवादों को किसी भी तरह पकड़ना होगा, तो यूआई के बजाए निचले स्तर पर क्यों रोना चाहिए? 2) यदि आप बहुत सी चीजें करते हैं तो आप संभवतः यूआई स्तर पर अपवाद प्रकारों को पकड़ सकते हैं। यह अविश्वसनीय रूप से कष्टप्रद है और UI पर तर्क के साथ आपका कोड लिटर करता है जो वास्तव में वहां नहीं होना चाहिए। दोबारा, आप मूल अपवाद को लपेट रहे हैं, ताकि आप अभी भी एक ही प्रकार को पकड़ सकें और बिना किसी कैच के अपने सभी निष्ठा आवश्यकताओं के लिए इनरएक्सप्शन की जांच कर सकें। 3) अन्य रिबूट हो सकते हैं लेकिन मैं उन्हें सूचीबद्ध करने के लिए बहुत आलसी हूं। – Will

    +0

    @ चार्ल्स प्रकाश दशरी: विफलता के प्रकार से प्रतिष्ठित अपवाद प्रकार वास्तव में उपयोगी नहीं है। सिस्टम राज्य द्वारा उन्हें प्रतिष्ठित करने के लिए और भी उपयोगी क्या है। उदाहरण के लिए, यदि किसी दिनचर्या को डेटाबेस में रिकॉर्ड अपडेट करना होता है और यह काम नहीं करता है, तो यह उपयोगकर्ता के लिए यह जानना उपयोगी हो सकता है कि यह लॉक टाइमआउट या टीसीपी कनेक्शन रीसेट से हुआ है, लेकिन प्रोग्राम स्टैंडपॉइंट से, क्या अधिक महत्वपूर्ण है यह जानना है कि ... – supercat

    0

    सबसे पहले वहाँ कोई एक ही रास्ता निश्चित रूप से है और वहाँ एक आदर्श एक तो यह overthink नहीं है नहीं है।

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

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

    तो कहते हैं कि एक अद्यतन मेरी भंडार में विफल रहता है अगर मैं आज़माएं/कैच होना चाहिए कि त्रुटि फेंकता है, तब मेरी सेवा परत यह फैल जाती है और elmah संकेत करता है और झूठे रिटर्न?

    अद्यतन क्यों विफल हो जाएगा? क्या यह सामान्य प्रक्रिया का हिस्सा होने के लिए एक बिल्कुल सही कारण है? फिर एक अजीब कारण के कारण ऐसा होने पर अपवाद फेंक न दें (मान लीजिए कि रिकॉर्ड को अपडेट होने से पहले अपडेट को अपडेट किया जा रहा है) तो एक अपवाद तार्किक है। इस स्थिति से ठीक होने का कोई रास्ता नहीं है।

    +0

    "आईडी और वस्तु से किसी वस्तु के लिए खोज नहीं पाया जाता है तो आप अशक्त वापस जाने के लिए चाहते हो जाएगा" ... और फिर नल के लिए आशा है कि अपने कॉलर की जाँच करता? यदि आप आईडी की अपेक्षा करते हैं (उपयोगकर्ता इनपुट नहीं), आम तौर पर फेंक दें। यदि आप निश्चित नहीं हैं, तो कोशिश करें-पार्स पैटर्न पर विचार करें। Http://blogs.msdn.com/kcwalina/archive/2005/03/16/396787.aspx – TrueWill

    +0

    देखें यह कॉलर पर कार्य करने से अपेक्षित परिणामों को समझने के लिए है। यदि कॉलर इस तथ्य को अनदेखा करता है कि हस्ताक्षर/दस्तावेज कहता है कि फ़ंक्शन नल वापस कर सकता है, तो कॉलर गलती पर फ़ंक्शन नहीं है। आईएमओएच इस मामले में रिटर्निंग नल पूरी तरह मान्य है। – BlackMael

    +0

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

    1

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

    int int.Parse(string integerValue); // In this case, the method will return int 
                // or it will die! That means your data must be 
                // valid for this method to function. 
    
    bool int.TryParse(string integerValue, out number); // In this case, we expect the data 
                    // we passed in might not be fully 
                    // valid, hence a boolean. 
    
    2

    एक त्रुटि (या सफलता) कोड अक्सर बेहतर तरीका है, अपवाद लौटने कोड के ऊपर एक विशाल लाभ है लौटते समय या चुपचाप त्रुटियों को दबाने: कम से कम आप उन्हें अनदेखा नहीं कर सकते हैं!

    सरल प्रवाह नियंत्रण के लिए अपवादों का दुरुपयोग न करें - यह करने के लिए सबसे शानदार चीज होगी।

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

    बस एक त्रुटि कोड लौटाना खतरनाक है क्योंकि कॉलर कोड का निरीक्षण करने से परेशान नहीं हो सकता है और संभवतः अभी भी आगे बढ़ सकता है - भले ही आपके ऐप के तर्क में, वास्तव में कुछ गलत है और इसके साथ निपटने की आवश्यकता है।

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

    अपवादों को संभालने के लिए: उन लोगों को संभालें जिन्हें आप वास्तव में सौदा कर सकते हैं। जैसे यदि आप फ़ाइल को सहेजने और सुरक्षा अपवाद प्राप्त करने का प्रयास करते हैं, तो उपयोगकर्ता को किसी अन्य स्थान को सहेजने के लिए एक संवाद दिखाएं (क्योंकि उसे उस स्थान को सहेजने की अनुमति नहीं हो सकती है जहां वह चाहता था)।

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

    +0

    एक दृष्टिकोण जो मैंने सिस्टम में उपयोग किया था, जिसमें अपवाद नहीं थे, एक आवश्यकता के साथ लचीला त्रुटि कोड को गठबंधन करना था कि एप्लिकेशन कोड स्पष्ट रूप से अगले I/O ऑपरेशन से पहले एक त्रुटि को स्वीकार/रीसेट कर सकता है या फिर अगला I/O ऑपरेशन घातक ट्रिगर करेगा त्रुटि (एक मामले में, मेरे पास गैर-घातक त्रुटि स्टैक और पैरामीटर मानों को कैप्चर करती है, जिसे तब जांच की जा सकती है जब त्रुटि को स्वीकार/रीसेट करने से पहले किसी अन्य I/O ऑपरेशन का प्रयास किया जाता है)। ऐसा दृष्टिकोण "आधुनिक" प्रतिमानों के साथ अच्छी तरह फिट नहीं है, लेकिन अपवाद उपलब्ध नहीं होने पर अच्छी तरह से काम करता है। – supercat

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