मुझे अपवाद के बारे में अतिरिक्त जानकारी कैसे प्रदान करनी चाहिए?


20

हर बार मुझे एक अपवाद के बारे में अतिरिक्त जानकारी प्रदान करने की आवश्यकता होती है, मुझे आश्चर्य होता है कि वास्तव में ऐसा करने का सही तरीका क्या है।


इस सवाल के लिए मैंने एक उदाहरण लिखा। मान लेते हैं कि एक वर्ग है जहाँ हम Abbreviationसंपत्ति को अद्यतन करना चाहते हैं। ठोस दृष्टिकोण से, यह सही नहीं हो सकता है, लेकिन भले ही हमने किसी सेवा के साथ डीआई के माध्यम से कार्यकर्ता-विधि पारित की हो , एक ही स्थिति उत्पन्न होती है - एक अपवाद होता है इसका कोई संदर्भ नहीं है। उदाहरण पर वापस जाएं ...

class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Abbreviation { get; set; }
}

फिर वर्ग और लूप के कुछ उदाहरण हैं जहां कार्यकर्ता-विधि कहा जाता है। यह फेंक सकता है StringTooShortException

var persons =
{
    new Person { Id = 1, Name = "Fo" },
    new Person { Id = 2, Name = "Barbaz" },
}

public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
    foreach (var person in persons)
    {
        try
        {
            person.Abbreviation = GenerateAbbreviation(person.Name);
        }
        catch(Exception ex)
        {
            // ?
        }
    }
    // throw AggregateException...
}

public IEnumerable<string> GenerateAbbreviation(string value)
{
    if (value.Length < 5)
    {
        throw new StringTooShortException(value);
    }

    // generate abbreviation
}

उद्धरण है: कैसे Personया इसके Id(या कुछ और) जोड़ने के लिए ?


मैं निम्नलिखित तीन तकनीकों को जानता हूं:


1 - Dataसंपत्ति का उपयोग करें

पेशेवरों:

  • अतिरिक्त जानकारी सेट करना आसान है
  • और भी अधिक अपवाद बनाने की आवश्यकता नहीं है
  • अतिरिक्त की आवश्यकता नहीं है try/catch

विपक्ष:

  • में आसानी से एकीकृत नहीं किया जा सकता है Message
  • लोग इस फ़ील्ड को अनदेखा करते हैं और इसे डंप नहीं करेंगे
  • कुंजियों की आवश्यकता होती है और डीसैस का मान कास्टिंग होता है object
  • अपरिवर्तनीय नहीं है

उदाहरण:

public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
    foreach (var person in persons)
    {
        try
        {
            person.Abbreviation = GenerateAbbreviation(person.Name);
        }
        catch(Exception ex)
        {
            ex.Data["PersonId"] = person.Id;
            // collect ex
        }
    }
    // throw AggregateException...
}

2 - कस्टम गुणों का उपयोग करें

पेशेवरों:

  • Dataसंपत्ति के समान लेकिन दृढ़ता से टाइप किया गया
  • में एकीकृत करने के लिए आसान है Message

विपक्ष:

  • कस्टम अपवाद की आवश्यकता है
  • लकड़हारा उनकी उपेक्षा करेगा
  • अपरिवर्तनीय नहीं है

उदाहरण:

public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
    foreach (var person in persons)
    {
        try
        {
            person.Abbreviation = GenerateAbbreviation(person.Name);
        }
        catch(Exception ex)
        {
            // not suitable for this exception because 
            // it doesn't have anything in common with the Person
        }
    }
    // throw AggregateException...
}

3 - अपवाद को दूसरे अपवाद के साथ लपेटें

पेशेवरों:

  • Message पूर्वानुमानित रूप में स्वरूपित किया जा सकता है
  • लकड़हारे आंतरिक अपवादों को छोड़ देंगे
  • अडिग

विपक्ष:

  • अतिरिक्त की आवश्यकता है try/catch
  • घोंसले के शिकार
  • शकों की गहराई का अनुमान लगाता है

उदाहरण:

public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
    foreach (var person in persons)
    {
        try
        {
            try
            {
                person.Abbreviation = GenerateAbbreviation(person.Name);
            }
            catch(Exception ex)
            {
                throw new InvalidPersonDataException(person.Id, ex);
            }
        }
        catch(Exception ex)
        {
            // collect ex
        }
    }
    // throw AggregateException...
}

  • क्या कोई अन्य पैटर्न हैं?
  • क्या बेहतर पैटर्न हैं?
  • क्या आप उनमें से किसी भी / सभी के लिए सर्वोत्तम अभ्यास सुझा सकते हैं?

C # में अपवादों से परिचित नहीं है, लेकिन मैं सामान्य तौर पर उम्मीद करूंगा कि अपवाद को फेंकने के दौरान व्यक्ति का उदाहरण अभी भी मान्य होगा। क्या आपने कोशिश की है?
जॉन कॉउरलिस

1
@JohnKouraklis यह वह सवाल नहीं है, जिसके बारे में ;-) यह सिर्फ एक अत्यंत सरल उदाहरण है, जो मुझे दिखाता है कि मुझे अतिरिक्त जानकारी से क्या मतलब है। अगर मैंने यहाँ एक पूरी रूपरेखा पोस्ट की है जहाँ उत्परिवर्ती तरीके अपवादों को फेंक सकते हैं और संदर्भ जानकारी के पारस्परिक स्तर को प्रदान किया जाना चाहिए, तो कोई भी शायद इसे नहीं पढ़ेगा और मेरे पास इसे समझाने के लिए बहुत कठिन समय था।
t3chb0t 21

@JohnKouraklis मैंने अभी इसे प्रदर्शन प्रयोजनों के लिए बनाया है।
t3chb0t 21

@ t3chb0t मुझे लगता है कि आपने यहां अपने प्रश्न का उत्तर दिया है। 1, 2, और 3 को एक उत्तर में ले जाने और अपने प्रश्न को समायोजित करने पर विचार करें, इसलिए यह मुझे मेरी राय के आधार पर एक शैली चुनने के लिए नहीं कह रहा है।
कैंडिड_ऑरेंज

कस्टम अपवादों में क्या गलत है? ठीक से किया, वे आपकी डोमेन भाषा का हिस्सा हैं और अमल विवरण से दूर अमूर्तता प्राप्त करने में मदद करते हैं।
रबरडुक

जवाबों:


6

Data FTW

आपका "जख्म":

  • "संदेश में आसानी से एकीकृत नहीं किया जा सकता है"

-> आपके अपवाद प्रकारों के लिए, ओवरराइड करने के लिए यह काफी आसान होना चाहिए Messageताकि वह इसमें शामिल हो जाए Data.. हालाँकि मैं केवल इस पर विचार करूंगा यदि Dataसंदेश है

  • "लकड़हारे इस क्षेत्र को अनदेखा कर देते हैं और उसे डंप नहीं करेंगे"

एक उदाहरण के रूप Nlog लिए Googling पैदावार :

अपवाद लेआउट रेंडरर

(...)

प्रारूप - आउटपुट का प्रारूप । अपवाद संपत्तियों की एक अल्पविराम से अलग किए होना चाहिए: Message, Type, ShortType, ToString, Method, StackTraceऔर Data। यह पैरामीटर मान केस-असंवेदनशील है। चूक:message

तो ऐसा लगता है कि यह आसानी से विन्यास योग्य है।

  • मान और ऑब्जेक्ट की आवश्यकता है क्योंकि कास्टिंग की आवश्यकता होती है

है ना? बस वहां वस्तुओं को डंप करें और सुनिश्चित करें कि उनके पास एक प्रयोग ToString()करने योग्य विधि है।

इसके अलावा, मैं चाबी के साथ किसी भी समस्या को नहीं देख रहा हूँ। बस कुछ सौम्य विशिष्टता का उपयोग करें और आप अच्छे हैं।


डिस्क्लेमर: यह वह है जिसे मैं तुरंत प्रश्न से देख सकता था और मैंने Data15 मिनट में क्या देखा। मुझे लगा कि यह हल्का मददगार है, इसलिए मैंने इसे एक उत्तर के रूप में सामने रखा, लेकिन मैंने Dataखुद को कभी इस्तेमाल नहीं किया है, इसलिए यह अच्छी तरह से हो सकता है कि यहां प्रश्नकर्ता मेरे बारे में इससे अधिक जानता हो।


मैं इस निष्कर्ष पर पहुंचा कि अपवाद के बारे में केवल दो चीजें हैं जो उपयोगी हैं, उसका नाम और संदेश। बाकी सब सिर्फ बेकार शोर है जिसे नजरअंदाज किया जाना चाहिए क्योंकि यह बहुत नाजुक है इस पर भरोसा करें।
t3chb0t

2

आप अपवाद क्यों फेंकते हैं? उन्हें पकड़ा और संभाला।

कैचिंग कोड एक्सेप्शन को कैसे हैंडल करता है? उन गुणों का उपयोग करना जो आप अपवाद ऑब्जेक्ट पर परिभाषित करते हैं।

अपवाद की पहचान करने के लिए कभी भी संदेश संपत्ति का उपयोग न करें, न ही "जानकारी" प्रदान करने के लिए कि किसी भी संभावित हैंडलर को भरोसा करना चाहिए। यह बस बहुत अस्थिर और अविश्वसनीय है।

मैंने पहले कभी भी "डेटा" प्रॉपर्टी का उपयोग नहीं किया है, लेकिन यह मुझे बहुत सामान्य लगता है।

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


1
मैं कहूंगा, Dataहैंडलिंग के लिए बेकार है, लेकिन लॉगिंग Messageनरक से बचने के लिए लॉगिंग के लिए मूल्यवान है।
मार्टिन बा

-1

मुझे आपका तीसरा उदाहरण पसंद है, हालांकि एक और तरीका है जिससे आपके अधिकांश "कॉन" को समाप्त करने के लिए कोडित किया जा सकता है।

public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
    var exceptions = new List<InvalidPersonDataException>();

    foreach (var person in persons)
    {
        try
        {
            person.Abbreviation = GenerateAbbreviation(person.Name);
        }
        catch(Exception ex)
        {
            exceptions.Add(new InvalidPersonDataException(person.Id, ex));
        }
    }

    if (exceptions.Any())
    {
        throw new AggregateException(exceptions);
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.