2010-11-06 90 views
28

टायर किए गए अनुप्रयोगों में अपवादों को संभालने के लिए सुझाए गए दृष्टिकोण या सर्वोत्तम अभ्यास क्या है?एन-स्तरीय अनुप्रयोगों में अपवाद हैंडलिंग?

  • आपको try/catch ब्लॉक कहां रखना चाहिए?
  • आपको लॉगिंग को कहां लागू करना चाहिए?
  • क्या एन-टियर वाले अनुप्रयोगों में अपवादों के प्रबंधन के लिए एक सुझाव दिया गया पैटर्न है?

एक साधारण उदाहरण पर विचार करें। मान लीजिए आप एक यूआई, कि एक व्यापार परत कहता है, जो डेटा स्तर कॉल:

//UI 
protected void ButtonClick_GetObject(object sender, EventArgs e) 
{ 
    try { 
     MyObj obj = Business.GetObj(); 
    } 
    catch (Exception ex) { 
     Logger.Log(ex); //should the logging happen here, or at source? 
     MessageBox.Show("An error occurred"); 
    } 
} 

//Business 
public MyObj GetObj() 
{ 
    //is this try/catch block redundant? 
    try { 
     MyObj obj = DAL.GetObj(); 
    } 
    catch (Exception ex) { 
     throw new Exception("A DAL Exception occurred", ex); 
    } 
} 

//DAL 
public MyObj GetObj() 
{ 
    //Or is this try/catch block redundant? 
    try { 
     //connect to database, get object 
    } 
    catch (SqlException ex) { 
     throw new Exception("A SQLException occurred", ex); 
    } 
} 

क्या आलोचनाओं आप ऊपर अपवाद संचालन के होगा?

धन्यवाद

+0

कोई स्वीकार्य उत्तर नहीं है? :/ – Vbp

उत्तर

3

ठीक करने के लिए पहली बात यह एक सामान्य Exception कभी नहीं फेंक होगा।

दूसरा, जब तक कि अपवाद को लपेटने के लिए वास्तव में कोई अच्छा कारण न हो, तो आपके पकड़ खंड में throw new... के बजाय throw; हो।

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

+0

ठीक है, धन्यवाद। व्यापार परत में कोशिश/पकड़ के बारे में क्या है जो प्रभावी रूप से कुछ भी नहीं करता है? क्या आपको हमेशा उन तरीकों से किसी भी कॉल को लपेटना चाहिए जो कोशिश किए बिना प्रयास/अपवाद में अपवाद फेंकते हैं, या आप केवल कुछ उच्च परत में कोशिश/पकड़ का उपयोग करना चाहिए? – flesh

17

अंगूठे का मेरा नियम आम तौर पर शीर्ष स्तर पर अपवाद पकड़ने और वहां लॉग (या अन्यथा रिपोर्ट) करने के लिए होता है, क्योंकि यह वह जगह है जहां आपको त्रुटि के बारे में अधिक जानकारी होती है - सबसे महत्वपूर्ण रूप से पूर्ण स्टैक ट्रेस।

, कुछ कारणों अन्य स्तरों में अपवाद को पकड़ने के लिए हो सकता है, लेकिन:

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

एकाधिक स्तरों पर एक ही त्रुटि लॉगिंग आम तौर पर उपयोगी नहीं है, लेकिन मैं एक अपवाद के बारे में सोच सकता हूं: जब निम्न स्तर को पता नहीं होता कि कोई समस्या महत्वपूर्ण है या नहीं, तो यह इसे चेतावनी के रूप में लॉग कर सकती है। यदि एक उच्च स्तरीय निर्णय लेता है कि महत्वपूर्ण है तो यह एक ही समस्या को एक त्रुटि के रूप में लॉग कर सकता है।

+2

धन्यवाद, यह वास्तव में एक उपयोगी उत्तर है। – flesh

2

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

  • अपवाद है कि केवल यदि आपका कोड गलत है होना चाहिए (या आप समझ में नहीं आता, या आप उन पर नियंत्रण नहीं है):

उदाहरण: हो सकता है कि अपने हठ ढांचे एसक्यूएल अपवाद विकृत एसक्यूएल से उत्पन्न हो सकते हैं, हालांकि, आप एक हार्ड कोडित क्वेरी को क्रियान्वित कर रहे हैं पकड़ने के लिए की आवश्यकता है।

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

आपको उच्च परतों में कुछ वापस करने की भी आवश्यकता होगी ताकि सर्वर पर जीवन चल रहा हो। शायद यह एक डिफ़ॉल्ट मान है, या शायद यह शून्य है। शायद आपके पास पूरे ऑपरेशन को रद्द करने का कोई तरीका है।

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

  • अपवाद है कि वास्तव में उपयोगकर्ता के कारण होता है:

उदाहरण: उपयोगकर्ता एक foobar विजेट का अद्यतन करें और यह एक नया नाम देने के लिए कोशिश कर रहा है, लेकिन एक foobar विजेट पहले से ही के साथ मौजूद है वह नाम जो वे चाहते हैं।

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

  • अपवाद कि आप वास्तव में संभाल कर सकते हैं:

उदाहरण: आप एक दूरस्थ सेवा कॉल और दूरस्थ सेवा का समय समाप्त कर, लेकिन आप जानते हैं कि वे ऐसा करने का इतिहास है और आपको चाहिए बस कॉल फिर से करें।

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

अपने उपरोक्त प्रश्न को संबोधित करने के लिए मैं उस सेवा के प्रारंभिक अपवाद को प्रतिनिधि दूंगा जो उपयोगकर्ता को सूचित करेगा और किस प्रकार की वस्तु MyObj है (उदाहरण के लिए सेटिंग्स) मैं इसे एक गैर-घातक अपवाद होने और डिफ़ॉल्ट रूप से वापस करने दे सकता हूं मूल्य या यदि मैं ऐसा नहीं कर सकता (जैसे उपयोगकर्ता खाता) तो मैं इसे घातक अपवाद दे सकता हूं इसलिए मुझे इसके बारे में चिंता करने की ज़रूरत नहीं है।

11

यहाँ मैं अपवाद हैंडलिंग से संबंधित पालन में कुछ नियम हैं:

  • अपवाद केवल परतों है कि उन्हें संभालने के लिए तर्क लागू कर सकते हैं में पकड़ा जाना चाहिए। ज्यादातर मामलों में यह ऊपरी परतों में होता है। अंगूठे के नियम के रूप में, एक परत के अंदर एक पकड़ को लागू करने से पहले, खुद से पूछें कि क्या ऊपरी परतों का तर्क अपवाद के अस्तित्व पर किसी भी तरह से निर्भर करता है। उदाहरण के लिए आपकी व्यावसायिक परत में आपके पास निम्न नियम हो सकता है: सेवा उपलब्ध होने पर बाहरी सेवा से डेटा लोड करें, यदि स्थानीय कैश से लोड नहीं होता है। यदि सेवा को कॉल करना एक एक्सप्शन फेंकता है तो आप इसे बीएल स्तर पर पकड़ और लॉग कर सकते हैं और फिर डेटा को कैश से वापस कर सकते हैं। ऊपरी यूआई परत को इस मामले में कोई कार्रवाई नहीं करनी पड़ती है। हालांकि, अगर सेवा और कैश कॉल दोनों विफल हो जाते हैं तो अपवाद को यूआई स्तर पर जाना होगा ताकि उपयोगकर्ता को एक त्रुटि संदेश प्रदर्शित किया जा सके।
  • किसी एप्लिकेशन के अंदर सभी अपवादों को पकड़ा जाना चाहिए और यदि उन्हें संभालने के लिए कोई विशेष तर्क नहीं है, तो उन्हें कम से कम लॉग इन होना चाहिए। बेशक, इसका मतलब यह नहीं है कि आपको कोशिश/पकड़ने वाले ब्लॉक में सभी विधियों से कोड लपेटना होगा। इसके बजाय किसी भी एप्लिकेशन प्रकार में अपरिपक्व अपवादों के लिए वैश्विक हैंडलर है। उदाहरण के लिए विंडोज अनुप्रयोगों में Application.ThreadException घटना लागू की जानी चाहिए। एएसपी में .NET अनुप्रयोगों को Application_Error ग्लोबल.एक्सएक्स से इवेंट हैंडलर लागू किया जाना चाहिए। ये स्थान ऊपरी अधिकतर स्थान हैं जहां आप अपने कोड में अपवाद पकड़ सकते हैं। कई अनुप्रयोगों में यह वह स्थान होगा जहां आप अधिकांश अपवादों को पकड़ेंगे और लॉगिंग के अलावा, यहां आप शायद एक सामान्य और मैत्रीपूर्ण त्रुटि संदेश विंडो भी लागू करेंगे जो उपयोगकर्ता को प्रस्तुत की जाएगी।
  • आप कोशिश/अंततः कार्यक्षमता को कार्यान्वित कर सकते हैं जहां आपको पकड़ ब्लॉक को लागू किए बिना इसकी आवश्यकता है। यदि आपको किसी अपवाद हैंडलिंग तर्क को लागू करने की आवश्यकता नहीं है तो एक कैच ब्लॉक लागू नहीं किया जाना चाहिए। उदाहरण के लिए:
SqlConnection conn = null; 
try 
{ 
    conn = new SqlConnection(connString); 
    ... 
} 
// do not implement any catch in here. db exceptions logic should be implemented at upper levels 
finally 
{ 
    // finalization code that should always be executed. 
    if(conn != null) conn.Dispose(); 
} 
  • यदि आप एक कैच ब्लॉक से एक अपवाद rethrow करने की जरूरत है कि बस द्वारा throw; का उपयोग कर। यह सुनिश्चित करेगा कि स्टैक ट्रेस संरक्षित है। throw ex; का उपयोग करके स्टैक ट्रेस रीसेट हो जाएगा।
  • यदि आपको किसी अन्य प्रकार के साथ अपवाद को दोबारा करने की आवश्यकता है जो ऊपरी स्तरों के लिए अधिक समझ में आती है, तो नए बनाए गए अपवाद की इनरएक्सप्शन संपत्ति में मूल अपवाद शामिल करें।
  • यदि आपको अपने कोड उपयोग से अपवादों को अर्थपूर्ण अपवाद प्रकारों को फेंकने की आवश्यकता है।
0

मैं प्रत्येक परत के लिए sepearate अपवाद क्लास (DALException, BLException, ...) लॉग इन करने के साथ हूँ:, (जैसे फाइल में) परत सीमाओं (यह व्यवस्थापक के लिए है) में अपवाद है क्योंकि उपयोगकर्ता केवल देखना चाहिए स्पष्ट और समझने योग्य त्रुटि संदेश। उन अपवादों को डीएएलबेस पर सौदा करना चाहिए जो सभी परतों पर सभी डेटा एक्सेस लेयर कैल्सिस द्वारा विरासत में मिला है। इसके साथ ही हम कुछ वर्गों में अपवाद हैंडलिंग को केंद्रीकृत कर सकते हैं और डेवलपर केवल लेयररेक्सप्शन फेंक देगा (ई।जी: DALException) अधिक जानकारी देखें MultiTier Exception Handling

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

  • कोई संबंधित समस्या नहीं^_^