एक अपवाद-हैंडलिंग तंत्र के बिना एक आधुनिक भाषा क्यों डिज़ाइन करें?


47

कई आधुनिक भाषाएँ समृद्ध अपवाद हैंडलिंग सुविधाएँ प्रदान करती हैं , लेकिन Apple की स्विफ्ट प्रोग्रामिंग भाषा अपवाद हैंडलिंग तंत्र प्रदान नहीं करती है

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

कैसे उदाहरण के लिए मैं सबसे अच्छा कुछ व्यक्त कर सकते हैं

try:
    operation_that_can_throw_ioerror()
except IOError:
    handle_the_exception_somehow()
else:
     # we don't want to catch the IOError if it's raised
    another_operation_that_can_throw_ioerror()
finally:
    something_we_always_need_to_do()

एक भाषा में (स्विफ्ट, उदाहरण के लिए) जिसमें अपवाद से निपटने की कमी है?


11
आप सूची में गो को जोड़ना चाह सकते हैं , यदि हम सिर्फ उपेक्षा करते हैं panicजो कि समान नहीं है। इसके अलावा वहाँ क्या कहा गया है, एक अपवाद एक प्रदर्शन करने के लिए एक परिष्कृत (लेकिन आरामदायक) तरीके से बहुत अधिक नहीं है GOTO, हालांकि कोई भी इसे स्पष्ट कारणों के लिए नहीं कहता है।
जेन्सजी

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

1
मैं आपको, @Robert को फॉलो नहीं कर रहा हूं। C ++ कचरा संग्रहण के बिना अपवादों का समर्थन करने का प्रबंधन करता है।
कार्ल बेवेलफेल्ट

3
@ कार्लबेलीफ़ेल्ट: बड़े खर्च में, जो मैं समझता हूं, उससे। तो फिर, क्या कोई चीज है जो C ++ में बिना किसी खर्च के, कम से कम प्रयास और आवश्यक डोमेन ज्ञान के लिए की गई है?
रॉबर्ट हार्वे

2
@ रोबर्टहेयर: अच्छी बात है। मैं उन लोगों में से एक हूं, जो इन चीजों के बारे में पर्याप्त नहीं सोचते हैं। मुझे लगता है कि एआरसी जीसी है, लेकिन, बेशक, यह नहीं है में lulled है। तो मूल रूप से (यदि मैं लोभी हूँ, मोटे तौर पर), अपवाद एक गंदी बात होगी (C ++ भले ही) एक भाषा में जहां नियंत्रण प्रवाह पर निर्भर वस्तुओं का निपटान?
अयोम

जवाबों:


33

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

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

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

मैं स्विफ्ट से परिचित नहीं हूं, लेकिन मैंने इसकी त्रुटि से निपटने के बारे में पढ़ा है, यह बताता है कि वे अधिक कार्यात्मक-शैली पैटर्न का पालन करने के लिए त्रुटि से निपटने का इरादा रखते हैं। मैंने कोड उदाहरणों के साथ successऔर failureब्लॉक देखे हैं जो फ्यूचर की तरह लगते हैं।

इस स्काला ट्यूटोरियलFuture से एक उदाहरण दिया गया है :

val f: Future[List[String]] = future {
  session.getRecentPosts
}
f onFailure {
  case t => println("An error has occured: " + t.getMessage)
}
f onSuccess {
  case posts => for (post <- posts) println(post)
}

आप देख सकते हैं कि इसमें अपवाद के रूप में आपके उदाहरण के समान संरचना है। futureब्लॉक एक की तरह है tryonFailureब्लॉक अपवाद संचालक की तरह है। स्काला में, अधिकांश कार्यात्मक भाषाओं में, Futureपूरी तरह से भाषा का उपयोग करके पूरी तरह से लागू की जाती है। अपवादों जैसे किसी विशेष वाक्य-विन्यास की आवश्यकता नहीं है। इसका मतलब है कि आप अपने खुद के समान निर्माणों को परिभाषित कर सकते हैं। शायद एक timeoutब्लॉक जोड़ें , उदाहरण के लिए, या लॉगिंग कार्यक्षमता।

इसके अतिरिक्त, आप भविष्य को पास कर सकते हैं, इसे फ़ंक्शन से वापस कर सकते हैं, इसे डेटा संरचना में संग्रहीत कर सकते हैं, या जो भी हो। यह प्रथम श्रेणी का मान है। आप अपवादों की तरह सीमित नहीं हैं जिन्हें सीधे स्टैक तक प्रचारित किया जाना चाहिए।

विकल्प कुछ अलग तरीके से त्रुटि से निपटने की समस्या को हल करते हैं, जो कुछ उपयोग मामलों के लिए बेहतर काम करता है। तुम सिर्फ एक विधि से नहीं अटके हो।

उन चीजों के प्रकार हैं जिन्हें आप "अपवादों को खो कर प्राप्त करते हैं।"


1
तो Futureअनिवार्य रूप से एक फ़ंक्शन से लौटाए गए मूल्य की जांच करने का एक तरीका है, इसके लिए प्रतीक्षा करने के लिए बिना रुके। स्विफ्ट की तरह, यह रिटर्न-वैल्यू आधारित है, लेकिन स्विफ्ट के विपरीत, रिटर्न वैल्यू की प्रतिक्रिया बाद के समय में हो सकती है (अपवादों की तरह थोड़ा सा)। सही?
20

1
आप एक Futureसही तरीके से समझते हैं , लेकिन मुझे लगता है कि आप स्विफ्ट का दुरुपयोग कर सकते हैं। इस स्टैकओवरफ़्लो उत्तर का पहला भाग देखें , उदाहरण के लिए।
कार्ल बेलेफेल्ट 20

हम्म, मैं स्विफ्ट के लिए नया हूं, इसलिए मुझे जवाब देना मुश्किल है। लेकिन अगर मैं गलत नहीं हूँ: जो अनिवार्य रूप से एक हैंडलर से गुजरता है जिसे बाद के समय में लागू किया जा सकता है; सही?
ओरोम

हाँ। त्रुटि होने पर आप मूल रूप से कॉलबैक बना रहे हैं।
कार्ल बेज़ेलफेल्ट

Eitherएक बेहतर उदाहरण होगा IMHO
पवेल प्राक्क

19

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

cleanMug();
brewCoffee();
pourCoffee();
drinkCoffee();

आप एक नज़र में नहीं बता सकते हैं कि इनमें से कोई भी प्रक्रिया अपवाद को फेंक सकती है या नहीं। आपको यह पता लगाने के लिए इनमें से प्रत्येक प्रक्रिया के प्रलेखन को पढ़ना होगा। (कुछ भाषाएं इस जानकारी के साथ टाइप सिग्नेचर को बढ़ाकर इसे थोड़ा आसान बना देती हैं।) उपरोक्त कोड किसी भी प्रक्रिया को फेंकने की परवाह किए बिना ठीक-ठीक संकलन करेगा, जिससे अपवाद को हैंडल करना वास्तव में आसान हो जाएगा।

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

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

विशेष रूप से, एक अलग सुविधा के रूप में लागू करने के बजाय टाइप सिस्टम में त्रुटि हैंडलिंग को एम्बेड करने से "अपवाद" का उपयोग उन अन्य चीजों के लिए किया जा सकता है जो त्रुटियों से संबंधित नहीं हैं। (यह अच्छी तरह से ज्ञात है कि अपवाद हैंडलिंग वास्तव में भिक्षुओं की संपत्ति है।)


क्या यह सही है कि वैकल्पिक सहित, स्विफ्ट की उस प्रकार की प्रणाली "शक्तिशाली प्रकार की प्रणाली" है जो इसे प्राप्त करती है?
ओरोम

2
हां, वैकल्पिक और, अधिक सामान्यतः, योग प्रकार (स्विफ्ट / जंग में "एनम" के रूप में संदर्भित) इसे प्राप्त कर सकते हैं। उन्हें उपयोग करने के लिए सुखद बनाने के लिए कुछ अतिरिक्त काम लगते हैं, हालांकि: स्विफ्ट में, यह वैकल्पिक चेनिंग सिंटैक्स के साथ प्राप्त किया जाता है; हास्केल में, यह मोनडिक डू-नोटेशन के साथ हासिल किया जाता है।
रफ़लविंड

एक "पर्याप्त रूप से शक्तिशाली प्रकार प्रणाली" एक स्टैक ट्रेस दे सकती है, अगर यह बहुत बेकार नहीं है
Paweł Prażak

1
+1 यह इंगित करने के लिए कि अपवाद नियंत्रण के प्रवाह को अस्पष्ट करते हैं। बस एक सहायक नोट के रूप में: यह इस कारण से है कि क्या अपवाद वास्तव में अधिक दुष्ट नहीं हैं goto: gotoएक एकल फ़ंक्शन तक ही सीमित है, जो कि एक बहुत छोटी रेंज है बशर्ते फ़ंक्शन वास्तव में छोटे हैं, अपवाद कुछ के पार gotoऔर अधिक कार्य करता है come from(देखें en.wikipedia.org/wiki/INTERCAL ;-))। यह बहुत अधिक कोड के किसी भी दो टुकड़ों को जोड़ सकता है, संभवतः कोड को कुछ तीसरे कार्यों पर छोड़ देता है। केवल एक चीज यह नहीं कर सकती है, जो gotoकर सकता है, वापस जा रहा है।
सेमीस्टर

2
@ PawełPrażak जब कई उच्च-क्रम के कार्यों के साथ काम करते हैं, तो स्टैक के निशान लगभग मूल्यवान नहीं होते हैं। इनपुट्स और आउटपुट के बारे में मजबूत गारंटी और साइड इफेक्ट्स से बचने के कारण इस अप्रत्यक्षता को भ्रामक बग पैदा करने से रोकते हैं।
जैक

11

यहां कुछ शानदार उत्तर हैं, लेकिन मुझे लगता है कि एक महत्वपूर्ण कारण पर पर्याप्त जोर नहीं दिया गया है: जब अपवाद होते हैं, तो वस्तुओं को अमान्य राज्यों में छोड़ा जा सकता है। यदि आप एक अपवाद को "पकड़" सकते हैं, तो आपका अपवाद हैंडलर कोड उन अमान्य वस्तुओं के साथ एक्सेस और काम करने में सक्षम होगा। जब तक कि उन वस्तुओं के लिए कोड पूरी तरह से लिखा नहीं गया था, जो कि बहुत ही मुश्किल है, बहुत ही गलत तरीके से चल रहा है।

उदाहरण के लिए, वेक्टर को लागू करने की कल्पना करें। यदि कोई आपके वेक्टर को ऑब्जेक्ट के एक सेट के साथ इंस्टेंट करता है, लेकिन इनिशियलाइज़ेशन के दौरान एक अपवाद होता है (शायद, कहते हैं, अपनी ऑब्जेक्ट्स को नई आवंटित मेमोरी में कॉपी करते हुए), तो वेक्टर कार्यान्वयन को इस तरह से सही ढंग से कोड करना बहुत मुश्किल है कि नहीं स्मृति लीक है। Stroustroup का यह लघु पेपर वेक्टर उदाहरण को कवर करता है

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

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


1
कैच का उद्देश्य किसी ऑब्जेक्ट को सुसंगत बनाना (या किसी चीज़ को समाप्त करना यदि वह संभव न हो) एक त्रुटि होने के बाद है।
जूलिनरॉज

@JoulinRouge मुझे पता है। लेकिन कुछ भाषाओं ने आपको यह मौका नहीं देने का फैसला किया है, बल्कि पूरी प्रक्रिया को क्रैश करने के लिए। उन भाषा डिजाइनरों को पता है कि आप किस तरह का क्लीनअप करना चाहते हैं, लेकिन यह निष्कर्ष निकाला है कि यह आपको देना बहुत मुश्किल है, और ऐसा करने में शामिल ट्रेड-ऑफ इसके लायक नहीं होगा। मुझे लगता है कि आप उनकी पसंद से सहमत नहीं हो सकते हैं ... लेकिन यह जानना मूल्यवान है कि उन्होंने इन विशेष कारणों से जानबूझकर चुनाव किया।
चार्ली फूल

6

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

जैसे कि यह failबहुत बार मुहावरेदार नहीं है । कुछ मामले जहां ऐसा होता है, उदाहरण के लिए, टेस्ट हार्नेस में (जो उपयोगकर्ता कोड की तरह नहीं जानता है), एक कंपाइलर के शीर्ष-स्तर (इसके बजाय अधिकांश कंपाइलर कांटा) के रूप में, या कॉलबैक को लागू करते समय। उपयोगकर्ता इनपुट पर

इसके बजाय, सामान्य मुहावरे का उपयोग उनResult त्रुटियों को स्पष्ट रूप से पारित करने के लिए टेम्पलेट का उपयोग करना है जिन्हें संभालना चाहिए। इस से काफी आसान बना दिया है मैक्रो , है जो आसपास किसी भी अभिव्यक्ति है कि पैदावार एक परिणाम लपेटा जा सकता है और सफल हाथ पैदावार अगर वहाँ एक है, या अन्यथा समारोह से जल्दी वापस आती है।try!

use std::io::IoResult;
use std::io::File;

fn load_file(name: &Path) -> IoResult<String>
{
    let mut file = try!(File::open(name));
    let s = try!(file.read_to_string());
    return Ok(s);
}

fn main()
{
    print!("{}", load_file(&Path::new("/tmp/hello")).unwrap());
}

1
तो क्या यह कहना उचित है कि यह भी (जैसे गो का दृष्टिकोण) स्विफ्ट के समान है, जो है assert, लेकिन नहीं catch?
ओरोम

1
स्विफ्ट में, कोशिश करो! का अर्थ है: हाँ मुझे पता है कि यह विफल हो सकता है, लेकिन मुझे यकीन है कि यह नहीं होगा, इसलिए मैं इसे संभाल नहीं रहा हूं, और अगर यह विफल हो जाता है तो मेरा कोड गलत है, इसलिए कृपया उस मामले में क्रैश करें।
gnasher729

6

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

अपवाद ज्यादातर एक विकास उपकरण हैं और अप्रत्याशित मामलों में उत्पादन से उचित त्रुटि रिपोर्ट प्राप्त करने का एक तरीका है।

चिंताओं को अलग करने के अलावा (केवल अप्रत्याशित त्रुटियों के साथ खुश रास्ता बनाम अप्रत्याशित त्रुटियों के लिए कुछ सामान्य हैंडलर तक पहुंचने के माध्यम से गिरना) एक अच्छी बात है, आपके कोड को अधिक पठनीय और बनाए रखने योग्य है, यह वास्तव में सभी संभव के लिए अपना कोड तैयार करना असंभव है। अनपेक्षितता को पूरा करने के लिए अनपेक्षित मामलों, यहां तक ​​कि त्रुटि हैंडलिंग कोड के साथ इसे ब्लोट करने से भी।

यह वास्तव में "अप्रत्याशित" का अर्थ है।

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

सरल उदाहरण: हैश मैप के एपीआई के दो तरीके हो सकते हैं:

Value get(Key)

तथा

Option<Value> getOption(key)

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

कोड को कभी भी असफल बुनियादी मान्यताओं से निपटने की कोशिश नहीं करनी चाहिए।

उन्हें छोड़कर और निश्चित रूप से अच्छी तरह से पठनीय अपवादों को फेंकने से।

अपवाद फेंकना बुराई नहीं है, लेकिन उन्हें पकड़ना हो सकता है। अप्रत्याशित त्रुटियों को ठीक करने का प्रयास न करें। कुछ स्थानों पर अपवादों को पकड़ो जहां आप कुछ लूप या ऑपरेशन जारी रखना चाहते हैं, उन्हें लॉग इन करें, शायद एक अज्ञात त्रुटि की रिपोर्ट करें, और यह बात है।

सभी जगह कैच ब्लॉक एक बहुत बुरा विचार है।

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

मुझे लगता है कि लोगों द्वारा अपवादों को रोकने का कारण और त्रुटि से निपटने के स्वचालन के लिए इस महत्वपूर्ण उपकरण को छोड़ने से बहुत दूर जाना और नई भाषाओं से चिंताओं को बेहतर ढंग से अलग करना बुरे अनुभव हैं।

वह, और कुछ गलतफहमी के बारे में कि वे वास्तव में किसके लिए अच्छे हैं।

मोनैडिक बाइंडिंग के माध्यम से EVERYTHING करके उनका अनुकरण करना आपके कोड को कम पठनीय और बनाए रखने योग्य बनाता है, और आप स्टैक ट्रेस के बिना समाप्त हो जाते हैं, जो इस दृष्टिकोण को बदतर बना देता है।

कार्यात्मक शैली त्रुटि हैंडलिंग अपेक्षित त्रुटि मामलों के लिए महान है।

अपवाद से निपटने को स्वचालित रूप से सभी बाकी का ख्याल रखने दें, यही वह है :)


3

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

स्विफ्ट में एक सुविधा है जो अपवाद हैंडलिंग की तरह दिखती है, लेकिन सिर्फ लागू त्रुटि हैंडलिंग है। ऐतिहासिक रूप से, ऑब्जेक्टिव-सी में काफी व्यापक त्रुटि हैंडलिंग पैटर्न था: एक विधि या तो एक BOOL (सफलता के लिए YES) या एक वस्तु संदर्भ (असफलता के लिए शून्य, सफलता के लिए शून्य नहीं) लौटेगी, और एक पैरामीटर है "NSError * का सूचक" जिसका उपयोग NSError संदर्भ को संग्रहीत करने के लिए किया जाएगा। स्विफ्ट स्वचालित रूप से इस तरह की विधि में कॉल को अपवाद हैंडलिंग की तरह देखती है।

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


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

2
 int result;
 if((result = operation_that_can_throw_ioerror()) == IOError)
 {
  handle_the_exception_somehow();
 }
 else
 {
   # we don't want to catch the IOError if it's raised
   result = another_operation_that_can_throw_ioerror();
 }
 result |= something_we_always_need_to_do();
 return result;

सी में आप ऊपर की तरह कुछ के साथ समाप्त होगा।

क्या ऐसी चीजें हैं जो मैं स्विफ्ट में नहीं कर सकता हूं जो मैं अपवादों के साथ कर सकता हूं?

नहीं, कुछ भी नहीं है। आप अपवादों के बजाय परिणाम कोड संभालना समाप्त करते हैं।
अपवाद आपको अपने कोड को पुनर्गठित करने की अनुमति देते हैं ताकि त्रुटि हैंडलिंग आपके खुश पथ कोड से अलग हो, लेकिन यह इसके बारे में है।


और, इसी तरह, ...throw_ioerror()अपवादों को फेंकने के बजाय त्रुटियों को वापस करने के लिए कहते हैं?
अयोम

1
@raxacoricofallapatorius यदि हम अपवाद का दावा कर रहे हैं तो अस्तित्व में नहीं है, तो मुझे लगता है कि कार्यक्रम विफलता पर विफलता कोड और सफलता पर 0 के सामान्य पैटर्न का अनुसरण करता है।
पत्थर के

1
@stonemal Rust और Haskell जैसी कुछ भाषाएं, एक त्रुटि कोड की तुलना में कुछ अधिक सार्थक लौटने के लिए टाइप सिस्टम का उपयोग करती हैं, बिना छिपे हुए निकास बिंदुओं को जोड़े बिना अपवाद करती हैं। उदाहरण के लिए, एक रस्ट फ़ंक्शन, एक Result<T, E>एनुम लौटा सकता है, जो या तो एक हो सकता है Ok<T>, या एक Err<E>, Tजिस प्रकार आप चाहते थे, और किसी Eत्रुटि का प्रतिनिधित्व करने वाला एक प्रकार होने के साथ। पैटर्न मिलान और कुछ विशेष विधियाँ सफलताओं और असफलताओं दोनों को संभालना आसान बनाती हैं। संक्षेप में, अपवादों की कमी को स्वतः कोड का मतलब न मानें।
8bittree

1

चार्ली के जवाब के अलावा:

कई अपवादों और पुस्तकों में देखे गए घोषित अपवाद हैंडलिंग के ये उदाहरण बहुत छोटे उदाहरणों पर ही बहुत स्मार्ट लगते हैं।

यहां तक ​​कि अगर आप अमान्य वस्तु स्थिति के बारे में तर्क देते हैं, तो वे हमेशा बड़े ऐप के साथ काम करते समय वास्तव में बहुत बड़ा दर्द उठाते हैं।

उदाहरण के लिए, जब आपको IO से निपटना होता है, तो कुछ क्रिप्टोग्राफी का उपयोग करते हुए, आपके पास 20 प्रकार के अपवाद हो सकते हैं जिन्हें 50 विधियों में से निकाला जा सकता है। आप की आवश्यकता होगी अपवाद हैंडलिंग कोड की मात्रा की कल्पना करें। अपवाद हैंडलिंग कोड की तुलना में कई गुना अधिक कोड लेगा।

वास्तव में आप जानते हैं कि जब अपवाद दिखाई नहीं देता है और आपको केवल इतना अपवाद हैंडलिंग लिखने की आवश्यकता नहीं होती है, तो आप अपवादों को अनदेखा करने के लिए बस कुछ वर्कअराउंड का उपयोग करते हैं। मेरे व्यवहार में, केवल 5% घोषित अपवादों को एक विश्वसनीय ऐप के लिए कोड में संभाला जाना चाहिए।


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