यह नियंत्रित करने के लिए पैरामीटर कि क्या अपवाद फेंकना है या अशक्त करना है - अच्छा अभ्यास?


24

मैं अक्सर ऐसे तरीकों / कार्यों के लिए आता हूं जिनमें एक अतिरिक्त बूलियन पैरामीटर होता है जो यह नियंत्रित करता है कि क्या विफलता पर एक अपवाद फेंक दिया गया है, या अशक्त लौटा दिया गया है।

पहले से ही इस बारे में चर्चा चल रही है कि इनमें से कौन सा मामला किस मामले में बेहतर है, इसलिए आइए यहां इस पर ध्यान केंद्रित न करें। उदाहरण के लिए देखें जादू का मान लौटाएँ, अपवाद छोड़ें या विफलता पर झूठा लौटें?

इसके बजाय हम यह मान लें कि एक अच्छा कारण है कि हम दोनों तरीकों का समर्थन करना चाहते हैं।

व्यक्तिगत रूप से मुझे लगता है कि इस तरह की विधि को दो में विभाजित किया जाना चाहिए: एक जो विफलता पर एक अपवाद फेंकता है, दूसरा वह जो विफलता पर अशक्त हो जाता है।

तो, कौन सा बेहतर है?

एक: $exception_on_failureपैरामीटर के साथ एक विधि ।

/**
 * @param int $id
 * @param bool $exception_on_failure
 *
 * @return Item|null
 *   The item, or null if not found and $exception_on_failure is false.
 * @throws NoSuchItemException
 *   Thrown if item not found, and $exception_on_failure is true.
 */
function loadItem(int $id, bool $exception_on_failure): ?Item;

बी: दो अलग-अलग तरीके।

/**
 * @param int $id
 *
 * @return Item|null
 *   The item, or null if not found.
 */
function loadItemOrNull(int $id): ?Item;

/**
 * @param int $id
 *
 * @return Item
 *   The item, if found (exception otherwise).
 *
 * @throws NoSuchItemException
 *   Thrown if item not found.
 */
function loadItem(int $id): Item;

संपादित करें: C: कुछ और?

बहुत से लोगों ने अन्य विकल्प सुझाए हैं, या दावा करते हैं कि ए और बी दोनों त्रुटिपूर्ण हैं। इस तरह के सुझाव या राय का स्वागत है, प्रासंगिक और उपयोगी है। एक पूर्ण उत्तर में ऐसी अतिरिक्त जानकारी हो सकती है, लेकिन यह भी मुख्य सवाल का जवाब देगा कि हस्ताक्षर / व्यवहार को बदलने के लिए एक पैरामीटर एक अच्छा विचार है या नहीं।

टिप्पणियाँ

मामले में कोई सोच रहा है: उदाहरण PHP में हैं। लेकिन मुझे लगता है कि यह सवाल तब तक भाषाओं पर लागू होता है जब तक वे कुछ हद तक PHP या जावा के समान होते हैं।


5
जबकि मुझे पीएचपी में काम करना है और मैं काफी कुशल हूं, इसकी बस एक खराब भाषा है, और इसकी मानक लाइब्रेरी सभी जगह है। संदर्भ के लिए eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design पढ़ें । तो यह वास्तव में आश्चर्यजनक नहीं है कि कुछ PHP डेवलपर्स बुरी आदतों को अपनाते हैं। लेकिन मैंने इस विशेष डिजाइन गंध को अभी तक नहीं देखा है।
पॉलिग्नोम

मुझे दिए गए उत्तरों में एक आवश्यक बिंदु याद आ रहा है: जब आप एक या दूसरे का उपयोग करेंगे। यदि कोई वस्तु अनपेक्षित नहीं होगी और आपको एक त्रुटि (घबराहट का समय) माना जाता है तो आप अपवाद विधि का उपयोग करेंगे। आप कोशिश करें ... विधि का उपयोग करें यदि किसी लापता वस्तु की संभावना नहीं है और निश्चित रूप से त्रुटि नहीं है, लेकिन संभावना है कि आप अपने सामान्य प्रवाह नियंत्रण में शामिल हैं।
मार्टिन माट


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

4
एक सुझाव: इसके बजाय loadItemOrNull(id), इस पर विचार करें कि क्या loadItemOr(id, defaultItem)आपके लिए समझ में आता है। यदि आइटम एक स्ट्रिंग या संख्या है, तो यह अक्सर होता है।
user949300

जवाबों:


35

आप सही हैं: दो तरीके हैं बहुत कई कारणों से, उस के लिए बेहतर:

  1. जावा में, विधि के हस्ताक्षर जो संभावित रूप से एक अपवाद को फेंकता है, इसमें यह अपवाद शामिल होगा; अन्य विधि नहीं होगी। यह विशेष रूप से स्पष्ट करता है कि एक और दूसरे से क्या उम्मीद की जाए।

  2. C # जैसी भाषाओं में जहां विधि के हस्ताक्षर अपवादों के बारे में कुछ नहीं बताते हैं, सार्वजनिक विधियों को अभी भी दस्तावेज होना चाहिए, और ऐसे प्रलेखन में अपवाद शामिल हैं। किसी एक विधि का दस्तावेजीकरण करना आसान नहीं होगा।

    आपका उदाहरण एकदम सही है: कोड के दूसरे टुकड़े में टिप्पणियाँ बहुत स्पष्ट दिखती हैं, और मैं भी "आइटम, यदि मिला (अन्यथा)।" आइटम "।" आइटम "- एक संभावित अपवाद और की उपस्थिति को कम कर देगा। आपके द्वारा दिया गया वर्णन आत्म-व्याख्यात्मक है।

  3. एकल विधि के एक मामले में, कुछ मामले हैं जहां आप रनटाइम पर बूलियन पैरामीटर के मूल्य को टॉगल करना चाहते हैं , और यदि आप ऐसा करते हैं, तो इसका मतलब होगा कि कॉलर को दोनों मामलों ( nullप्रतिक्रिया और अपवाद) को संभालना होगा ), कोड को और अधिक कठिन बनाने की तुलना में इसे करने की आवश्यकता है। चूंकि चुनाव रनटाइम पर नहीं किया जाता है, लेकिन कोड लिखते समय, दो विधियाँ सही अर्थ बनाती हैं।

  4. कुछ फ्रेमवर्क, जैसे .NET फ्रेमवर्क, ने इस स्थिति के लिए सम्मेलनों की स्थापना की है, और वे इसे दो तरीकों से हल करते हैं, जैसे आपने सुझाव दिया था। अंतर केवल इतना है कि वे अपने उत्तर में इवान द्वारा बताए गए एक पैटर्न का उपयोग करते हैं , इसलिए int.Parse(string): intएक अपवाद नहीं फेंकता है, जबकि int.TryParse(string, out int): boolऐसा नहीं है। यह नामकरण सम्मेलन .NET के समुदाय में बहुत मजबूत है और जब भी कोड आपके द्वारा वर्णित स्थिति से मेल खाता है, उसका पालन किया जाना चाहिए।


1
धन्यवाद, यह वह उत्तर है जिसकी मुझे तलाश थी! उद्देश्य यह था कि मैं इस बारे में Drupal CMS, drupal.org/project/drupal/issues/2932772 पर चर्चा शुरू करूं, और मैं नहीं चाहता कि यह मेरी व्यक्तिगत पसंद के बारे में हो, लेकिन दूसरों से प्रतिक्रिया लेकर इसे वापस लें।
donquixote

4
वास्तव में कम से कम .NET के लिए लंबे समय से चली आ रही परंपरा दो तरीकों का उपयोग करने के लिए नहीं है, बल्कि सही कार्य के लिए सही विकल्प चुनें। अपवाद असाधारण परिस्थितियों के लिए हैं, अपेक्षित नियंत्रण प्रवाह को संभालने के लिए नहीं। एक पूर्णांक में एक स्ट्रिंग पार्स करने में असफल? बहुत अप्रत्याशित या असाधारण परिस्थिति नहीं है। int.Parse()वास्तव में खराब डिजाइन निर्णय माना जाता है, यही कारण है कि .NET टीम आगे बढ़ी और कार्यान्वित हुई TryParse
वू

1
हम किस तरह के उपयोग के मामले से निपटने के बारे में सोचने के बजाय दो तरीके प्रदान करते हैं, यह आसान तरीका है: आप जो कर रहे हैं उसके बारे में मत सोचो, इसके बजाय अपने एपीआई के सभी उपयोगकर्ताओं पर जिम्मेदारी डालें। यकीन है कि यह काम करता है, लेकिन यह अच्छे एपीआई डिजाइन (या मामले के लिए किसी भी डिजाइन) की बानगी नहीं है। उदाहरण के लिए जोएल का इस पर ध्यान दें
वू

@Voo मान्य बिंदु। वास्तव में दो तरीके प्रदान करना कॉलर पर विकल्प डालता है। शायद कुछ पैरामीटर मानों के लिए एक आइटम के अस्तित्व की उम्मीद है, जबकि अन्य पैरामीटर मूल्यों के लिए एक गैर-मौजूदा आइटम को एक नियमित मामला माना जाता है। शायद घटक का उपयोग एक एप्लिकेशन में किया जाता है जहां आइटम हमेशा मौजूद रहने की उम्मीद करते हैं, और एक अन्य एप्लिकेशन में जहां गैर-मौजूदा आइटम को सामान्य माना जाता है। शायद कॉल करने ->itemExists($id)से पहले कॉलर कॉल करता है ->loadItem($id)। या शायद यह अतीत में अन्य लोगों द्वारा बनाई गई एक पसंद है, और हमें इसे स्वीकार करना होगा।
दान करें

1
कारण 1 बी: कुछ भाषाओं (हास्केल, स्विफ्ट) को हस्ताक्षर में मौजूद होने के लिए अशक्तता की आवश्यकता होती है। विशेष रूप से, हास्केल के पास अशक्त मूल्यों ( data Maybe a = Just a | Nothing) के लिए एक पूरी तरह से अलग प्रकार है ।
जॉन

9

एक दिलचस्प बदलाव स्विफ्ट भाषा है। स्विफ्ट में, आप एक फ़ंक्शन को "फेंकने" के रूप में घोषित करते हैं, यही है कि इसे त्रुटियों को फेंकने की अनुमति है (इसी तरह लेकिन काफी हद तक जावा अपवाद के रूप में नहीं)। कॉलर इस फ़ंक्शन को चार तरीकों से कॉल कर सकता है:

ए। एक कोशिश / कैच स्टेटमेंट में अपवाद को पकड़ना और संभालना।

ख। यदि कॉल करने वाले को खुद को फेंकने के रूप में घोषित किया जाता है, तो बस कॉल करें, और फेंकी गई कोई भी त्रुटि कॉलर द्वारा फेंकी गई त्रुटि में बदल जाती है।

सी। फ़ंक्शन कॉल को चिह्नित करना try!जिसका अर्थ है "मुझे यकीन है कि यह कॉल फेंकने वाला नहीं है"। कहा जाता समारोह तो करता है फेंक, अनुप्रयोग क्रैश करने के लिए गारंटी है।

घ। फ़ंक्शन कॉल को चिह्नित करना try?जिसका अर्थ है "मुझे पता है कि फ़ंक्शन फेंक सकता है लेकिन मुझे परवाह नहीं है कि कौन सी त्रुटि वास्तव में फेंक दी गई है"। यह फ़ंक्शन के रिटर्न मान को " T" से टाइप " optional<T>" में बदल देता है, और फेंके गए अपवाद को रिटर्निंग नील में बदल दिया जाता है।

(ए) और (डी) ऐसे मामले हैं जिनके बारे में आप पूछ रहे हैं। क्या होगा अगर फ़ंक्शन शून्य वापस कर सकता है और अपवाद फेंक सकता है? उस मामले में optional<R>कुछ प्रकार आर के लिए वापसी मूल्य का प्रकार " " होगा , और (डी) इसे " optional<optional<R>>" में बदल देगा जो कि थोड़ा गुप्त और समझने में कठिन है लेकिन पूरी तरह से ठीक है। और एक स्विफ्ट फ़ंक्शन वापस आ सकता है optional<Void>, इसलिए (d) शून्य को लौटाने वाले कार्यों को फेंकने के लिए उपयोग किया जा सकता है।


2

मुझे bool TryMethodName(out returnValue)अप्रोच पसंद है ।

यह आपको इस बात का निर्णायक संकेत देता है कि विधि सफल हुई या नहीं और नामकरण मैच को पकड़ने की कोशिश पद्धति में अपवाद फेंकने की विधि को लपेटता है।

यदि आप बस अशक्त लौटते हैं, तो आप यह नहीं जानते कि यह विफल हुआ या रिटर्न वैल्यू वैध रूप से अशक्त था।

उदाहरण के लिए:

//throws exceptions when error occurs
Item LoadItem(int id);

//returns false when error occurs
bool TryLoadItem(int id, out Item item)

उदाहरण का उपयोग (संदर्भ के माध्यम से पास का मतलब अनधिकृत है)

Item i;
if(TryLoadItem(3, i))
{
    Print(i.Name);
}
else
{
    Print("unable to load item :(");
}

क्षमा करें, आपने मुझे यहां खो दिया। bool TryMethodName(out returnValue)मूल उदाहरण में आपका " दृष्टिकोण" कैसा होगा ?
दान करें

एक उदाहरण जोड़ने के लिए संपादित
इवान

1
इसलिए आप रिटर्न वैल्यू के बजाय बाय-रेफरेंस पैरामीटर का उपयोग करते हैं, इसलिए आपके पास बूल की सफलता के लिए रिटर्न वैल्यू फ्री है? क्या कोई प्रोग्रामिंग भाषा है जो इस "आउट" कीवर्ड का समर्थन करती है?
दान करें

2
हाँ, खेद फ्लॉप एहसास 'बाहर' ग # के लिए विशिष्ट है
ईवान

1
हमेशा नहीं। लेकिन क्या आइटम 3 अगर है अशक्त? आपको नहीं पता होगा कि कोई त्रुटि हुई है या नहीं
ईवान

2

आमतौर पर एक बूलियन पैरामीटर इंगित करता है कि एक फ़ंक्शन को दो में विभाजित किया जा सकता है, और एक नियम के रूप में आपको हमेशा बूलियन में पास होने के बजाय इसे विभाजित करना चाहिए।


1
मैं कुछ योग्यता या बारीकियों को जोड़े बिना इसे नियम के रूप में नहीं छोड़ूंगा। एक बूलियन को तर्क के रूप में हटाने से आपको एक गूंगा लिखने के लिए मजबूर किया जा सकता है अगर / किसी और जगह पर और इस प्रकार आप अपने लिखित कोड में डेटा को एनकोड करते हैं और चर में नहीं।
गेरार्ड

@ क्या आप मुझे एक उदाहरण दे सकते हैं?
अधिकतम

@ मोम जब आपके पास एक बूलियन चर होता है b: कॉल करने के बजाय foo(…, b);आपको if (b) then foo_x(…) else foo_y(…);अन्य तर्कों को लिखना और दोहराना पड़ता है , या ऐसा कुछ होता है जैसे ((b) ? foo_x : foo_y)(…)कि भाषा में एक टर्नरी ऑपरेटर और प्रथम श्रेणी के कार्य / विधियाँ होती हैं। और यह शायद कार्यक्रम में कई अलग-अलग स्थानों से दोहराया गया।
डांडा

@ बेलजैक अच्छी तरह से हाँ मैं आपसे सहमत हो सकता हूं। मैंने उदाहरण के बारे में सोचा, if (myGrandmaMadeCookies) eatThem() else makeFood()जो हाँ मैं इस तरह से किसी अन्य फ़ंक्शन में लपेट सकता हूं checkIfShouldCook(myGrandmaMadeCookies)। मुझे आश्चर्य है कि अगर आपके द्वारा बताई गई बारीकियों का इस बात से कोई लेना-देना नहीं है कि हम बूलियन में कैसे गुजर रहे हैं, तो हम चाहते हैं कि फ़ंक्शन कैसे व्यवहार करे, जैसा कि मूल प्रश्न में है, बनाम हम अपने मॉडल के बारे में कुछ जानकारी से गुजर रहे हैं, जैसे कि दादी उदाहरण मैंने अभी दिया।
मैक्स

1
मेरी टिप्पणी में निर्दिष्ट बारीकियों का तात्पर्य "आपको हमेशा होना चाहिए" से है। शायद इसे rephrase के रूप में "यदि a, b और c लागू हैं तो [...]"। आपके द्वारा उल्लेखित "नियम" एक महान प्रतिमान है, लेकिन उपयोग-मामले पर बहुत भिन्न है।
जेरार्ड

1

बूलियन ध्वज के तर्कों से बचने के लिए क्लीन कोड सलाह देता है, क्योंकि उनका अर्थ कॉल साइट पर अपारदर्शी है:

loadItem(id, true) // does this throw or not? We need to check the docs ...

जबकि अलग-अलग विधियाँ अभिव्यंजक नामों का उपयोग कर सकती हैं:

loadItemOrNull(id); // meaning is obvious; no need to refer to docs

1

यदि मुझे ए या बी का उपयोग करना था तो मैं आर्सेनी मूरजेनोस जवाब में बताए गए कारणों के लिए बी, दो अलग-अलग तरीकों का उपयोग करूंगा

लेकिन एक और विधि है 1 : जावा में इसे कहा जाता है Optional, लेकिन आप उसी अवधारणा को अन्य भाषाओं में लागू कर सकते हैं जहां आप अपने स्वयं के प्रकारों को परिभाषित कर सकते हैं, यदि भाषा पहले से ही समान वर्ग प्रदान नहीं करती है।

आप अपनी विधि को इस तरह परिभाषित करते हैं:

Optional<Item> loadItem(int id);

अपनी विधि में आप या तो वापस लौटते हैं Optional.of(item)यदि आपको आइटम मिला है या आप उस स्थिति Optional.empty()में लौटते हैं जब आप नहीं करते हैं। तुम कभी 2 फेंकते हो और कभी लौटते नहीं null

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

  • loadItem(1).get()फेंक दिया NoSuchElementExceptionया पाया आइटम वापस कर देगा ।
  • भी नहीं है loadItem(1).orElseThrow(() -> new MyException("No item 1"))अगर लौटे एक कस्टम अपवाद उपयोग करने के लिए Optionalखाली है।
  • loadItem(1).orElse(defaultItem)बिना किसी अपवाद के पाया गया वस्तु या पारित defaultItem(जो भी हो सकता है null) या तो देता है।
  • loadItem(1).map(Item::getName)Optionalयदि वर्तमान में फिर से आइटम नाम के साथ वापस आ जाएगा ।
  • कुछ और तरीके हैं, के लिए JavadocOptional देखें ।

लाभ यह है कि अब यह क्लाइंट कोड पर निर्भर है कि क्या होना चाहिए अगर कोई आइटम नहीं है और फिर भी आपको केवल एक विधि प्रदान करने की आवश्यकता है ।


1 मैं इसे की तरह कुछ है लगता है कि try?में gnasher729s जवाब लेकिन यह पूरी तरह से मेरे लिए स्पष्ट नहीं है के रूप में मैं स्विफ्ट पता नहीं है और यह तो यह स्विफ्ट के लिए विशिष्ट है एक भाषा सुविधा हो रहा है।

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


0

एक और बिंदु के रूप में दो तरीकों का उपयोग करके सहमत होना, यह लागू करना बहुत आसान हो सकता है। मैं अपना उदाहरण C # में लिखूंगा, क्योंकि मुझे PHP के सिंटैक्स की जानकारी नहीं है।

public Widget GetWidgetOrNull(int id) {
    // All the lines to get your item, returning null if not found
}

public Widget GetWidget(int id) {
    var widget = GetWidgetOrNull(id);

    if (widget == null) {
        throw new WidgetNotFoundException();
    }

    return widget;
}

0

मैं दो तरीकों को पसंद करता हूं, इस तरह, आप न केवल मुझे बताएंगे कि आप एक मूल्य वापस कर रहे हैं, लेकिन कौन सा मूल्य।

public int GetValue(); // If you can't get the value, you'll throw me an exception
public int GetValueOrDefault(); // If you can't get the value, you'll return me 0, since it's the default for ints

TryDoSomething () एक बुरा पैटर्न भी नहीं है।

public bool TryParse(string value, out int parsedValue); // If you return me false, I won't bother checking parsedValue.

मुझे डेटाबेस इंटरैक्शन में पूर्व देखने के लिए अधिक उपयोग किया जाता है जबकि बाद में पार्स सामान में अधिक उपयोग किया जाता है।

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


-1

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

Thing getThing(string x);
Thing tryGetThing (string x);

और एक ऐसे कार्य चाहते हैं जो इसी तरह व्यवहार करते हैं लेकिन एक्स कोष्ठक में लिपटे होने के साथ, आवरण कार्यों के दो सेट लिखना आवश्यक होगा:

Thing getThingWithBrackets(string x)
{
  getThing("["+x+"]");
}
Thing tryGetThingWithBrackets (string x);
{
  return tryGetThing("["+x+"]");
}

यदि त्रुटियों को कैसे प्रबंधित किया जाए, इसके लिए एक तर्क है, केवल एक आवरण की आवश्यकता होगी:

Thing getThingWithBrackets(string x, bool returnNullIfFailure)
{
  return getThing("["+x+"]", returnNullIfFailure);
}

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

Thing getThingWithBrackets(string x)
{
   return getThingWithBrackets(x, false);
}
Thing tryGetThingWithBrackets(string x)
{
   return tryGetThingWithBrackets(x, true);
}

सभी सभी "व्यावसायिक तर्क" को एक विधि में रख सकते हैं - वह जो एक तर्क को स्वीकार करता है जो यह दर्शाता है कि विफलता के मामले में क्या करना है।


आप सही हैं: सज्जाकार और रैपर, और यहां तक ​​कि नियमित रूप से कार्यान्वयन, दो तरीकों का उपयोग करते समय कुछ कोड दोहराव होगा।
२२

निश्चित रूप से अलग-अलग पैकेजों में अपवाद-फेंकने के साथ संस्करणों को डालें, और रैपर को सामान्य बनाएं?
विल क्रॉफर्ड

-1

मुझे लगता है कि सभी जवाब जो बताते हैं कि आपके पास ऐसा झंडा नहीं होना चाहिए जो यह नियंत्रित करे कि कोई अपवाद फेंका गया है या नहीं। उनकी सलाह किसी को भी मेरी सलाह होगी जो उस सवाल को पूछने की आवश्यकता महसूस करता है।

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

आप पा सकते हैं कि आपके पास अपने एपीआई के दो अलग-अलग उपयोगकर्ता हैं, जिनमें से एक अपवाद चाहता है और एक ऐसा नहीं है। एक वास्तविक जीवन उदाहरण जहां यह हो सकता है एक पुस्तकालय के साथ है जिसका उपयोग विकास और एम्बेडेड सिस्टम दोनों में किया जाता है। विकास के वातावरण में, उपयोगकर्ताओं को हर जगह अपवाद होने की संभावना होगी। अप्रत्याशित परिस्थितियों से निपटने के लिए अपवाद बहुत लोकप्रिय हैं। हालाँकि, उन्हें कई एम्बेडेड स्थितियों में निषिद्ध किया जाता है क्योंकि वे वास्तविक समय की बाधाओं का विश्लेषण करने में बहुत कठिन होते हैं। जब आप वास्तव में न केवल आपके कार्य को निष्पादित करने में लगने वाले औसत समय के बारे में परवाह करते हैं, बल्कि किसी एक व्यक्ति के मज़े के लिए समय लगता है, तो किसी भी मनमाने स्थान पर स्टैक को खोलने का विचार बहुत अवांछनीय है।

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

एम्बेडेड प्लेटफॉर्म पर, आप उन अपवादों को नहीं चाहते हैं। यह एक चेक करने के लिए और अधिक समझ में आता है if (this->mag() == 0) return Vector(0, 0, 0);। वास्तव में, मैं इसे वास्तविक कोड में देखता हूं।

अब किसी व्यवसाय के दृष्टिकोण से सोचें। आप API का उपयोग करने के दो अलग-अलग तरीके सिखाने की कोशिश कर सकते हैं:

// Development version - exceptions        // Embeded version - return 0s
Vector right = forward.cross(up);          Vector right = forward.cross(up);
Vector localUp = right.cross(forward);     Vector localUp = right.cross(forward);
Vector forwardHat = forward.unit();        Vector forwardHat = forward.tryUnit();
Vector rightHat = right.unit();            Vector rightHat = right.tryUnit();
Vector localUpHat = localUp.unit()         Vector localUpHat = localUp.tryUnit();

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

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.