संभवतः बेकार अपवाद हैंडलिंग के साथ कोड को मजबूत करना


12

क्या बेकार अपवाद को लागू करने के लिए यह एक अच्छा अभ्यास है, बस अगर कोड का एक और हिस्सा सही तरीके से कोडित नहीं है?

मूल उदाहरण

एक साधारण, इसलिए मैं हर किसी को ढीला नहीं करता हूं :)।

मान लीजिए कि मैं एक ऐप लिख रहा हूं जो किसी व्यक्ति की जानकारी (नाम, पता, आदि) प्रदर्शित करेगा, डेटा एक डेटाबेस से निकाला जा रहा है। मान लीजिए कि मैं UI भाग को कोड कर रहा हूं, और कोई अन्य व्यक्ति DB क्वेरी कोड लिख रहा है।

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

क्या होगा यदि क्वेरी खराब कोडित है और इस मामले को नहीं संभालती है? क्या होगा यदि क्वेरी लिखने वाला व्यक्ति आपको अपूर्ण परिणाम देता है, और जब आप informations को प्रदर्शित करने का प्रयास करते हैं, तो सब कुछ क्रैश हो जाता है, क्योंकि आपका कोड खाली सामान प्रदर्शित करने के लिए तैयार नहीं है?

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

एक और उदाहरण

मान लीजिए कि अब मैं क्वेरी लिख रहा हूं। विनिर्देशों को ऊपर के समान नहीं कहा जाता है, लेकिन "इन्सर्ट" क्वेरी लिखने वाले व्यक्ति को यह सुनिश्चित करना चाहिए कि अपूर्ण जानकारी डालने से बचने के लिए डेटाबेस में किसी व्यक्ति को जोड़ते समय सभी फ़ील्ड पूर्ण हो जाएं। क्या मुझे यह सुनिश्चित करने के लिए अपने "चयन" क्वेरी की रक्षा करनी चाहिए कि मैं UI आदमी को पूरा सुझाव दूं?

प्रश्न

क्या होगा अगर विनिर्देशों को स्पष्ट रूप से यह नहीं कहा जाता है कि "यह आदमी इस स्थिति को संभालने का प्रभारी है"? यदि कोई तीसरा व्यक्ति किसी अन्य क्वेरी (पहले वाले के समान, लेकिन किसी अन्य DB पर) को लागू करता है और उसे प्रदर्शित करने के लिए आपके UI कोड का उपयोग करता है, लेकिन अपने कोड में इस मामले को नहीं संभालता है?

क्या मुझे एक संभावित दुर्घटना को रोकने के लिए आवश्यक होना चाहिए, भले ही मैं खराब मामले को संभालने वाला न हो?

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

सामान्य तौर पर, यह प्रश्न निरर्थक अपवाद से निपटने से निपटता है। मैं यह इसलिए पूछ रहा हूं क्योंकि जब मैं किसी प्रोजेक्ट पर अकेले काम करता हूं, तो मैं एक ही अपवाद के क्रम में 2-3 बार कोडिंग कर सकता हूं, "सिर्फ मामले में" मैंने कुछ गलत किया और एक बुरे मामले को आने दिया।


4
आप "परीक्षण" के बारे में बात कर रहे हैं, लेकिन जहां तक ​​मैं आपकी समस्या को समझता हूं, तो इसका मतलब है कि "परीक्षण जो उत्पादन में लागू होते हैं", इसे "सत्यापन" या "अपवाद हैंडलिंग" कहा जाता है।
डॉक ब्राउन

1
हां, उपयुक्त शब्द "अपवाद हैंडलिंग" है।
रदुरंद

फिर गलत टैग को बदल दिया
डॉक्टर ब्राउन ने

मैं आपको डेली डब्ल्यूटीएफ का उल्लेख करता हूं - क्या आप सुनिश्चित हैं कि आप इस तरह का परीक्षण करना चाहते हैं?
gbjbaanb

@gbjbaanb: अगर मैं आपके लिंक को सही ढंग से समझता हूं, तो यह बिल्कुल नहीं है कि मैं किस बारे में बात कर रहा हूं। मैं "बेवकूफ परीक्षणों" के बारे में बात नहीं कर रहा हूं, मैं अपवाद से निपटने की नकल के बारे में बात कर रहा हूं।
रदुरंड

जवाबों:


14

यहाँ आप जिस बारे में बात कर रहे हैं वह है विश्वास सीमाएँ । क्या आपको अपने एप्लिकेशन और डेटाबेस के बीच की सीमा पर भरोसा है? क्या डेटाबेस को भरोसा है कि एप्लिकेशन से डेटा हमेशा पूर्व-मान्य है?

यह एक ऐसा निर्णय है जिसे हर आवेदन में किया जाना है और इसके सही और गलत उत्तर नहीं हैं। मैं कई सीमाओं को एक विश्वास सीमा कहने के पक्ष में गलत कर रहा हूं, अन्य डेवलपर्स खुशी-खुशी तीसरे पक्ष के एपीआई पर भरोसा करेंगे, जो आप उनसे हर समय, हर समय करने की उम्मीद करते हैं।


5

प्रबलता सिद्धांत "जो आप भेजते हैं उसमें रूढ़िवादी रहें, जो आप स्वीकार करते हैं उसमें उदार रहें" जो आप हैं। यह एक अच्छा सिद्धांत है - EDIT: जब तक इसका आवेदन कोई गंभीर त्रुटि नहीं छिपाता है - लेकिन मैं @pdr से सहमत हूं कि यह हमेशा उस स्थिति पर निर्भर करता है यदि आपको इसे लागू करना चाहिए या नहीं।


कुछ लोग सोचते हैं कि "मजबूती सिद्धांत" बकवास है। लेख एक उदाहरण देता है।

@MattFenwick: यह इंगित करने के लिए धन्यवाद, इसका वैध बिंदु, मैंने अपना उत्तर थोड़ा बदल दिया है।
डॉक ब्राउन

2
यह "मजबूती के सिद्धांत" के साथ समस्याओं की ओर इशारा करते हुए एक और बेहतर लेख है: joelonsoftware.com/items/2008/03/17.html
hakoja

1
@ ढोजा: ईमानदारी से, मैं इस लेख को अच्छी तरह से जानता हूं, यह उन समस्याओं के बारे में है, जब आप मजबूती के सिद्धांत का पालन नहीं करना शुरू करते हैं (जैसे कुछ एमएस लोग नए IE संस्करणों के साथ कोशिश करते हैं)। फिर भी, यह मूल प्रश्न से थोड़ा दूर हो जाता है।
डॉक ब्राउन

1
@DocBrown: यही कारण है कि आप जो स्वीकार करते हैं उसमें आपको कभी उदार नहीं होना चाहिए था। रोबस्टनेस का मतलब यह नहीं है कि आपको बिना किसी शिकायत के आप पर फेंकी गई हर चीज को स्वीकार करने की जरूरत है, बस आपको बिना सोचे-समझे आपके ऊपर फेंकी गई हर चीज को स्वीकार करने की जरूरत है।
मार्जन वेनमा

1

यह इस बात पर निर्भर करता है कि आप क्या परीक्षण कर रहे हैं; लेकिन मान लें कि आपके परीक्षण का दायरा केवल आपका अपना कोड है। उस स्थिति में, आपको परीक्षण करना चाहिए:

  • "खुश मामला": अपने आवेदन को मान्य इनपुट खिलाएं और सुनिश्चित करें कि यह सही आउटपुट का उत्पादन करता है।
  • विफलता के मामले: अपने आवेदन अमान्य इनपुट फ़ीड और सुनिश्चित करें कि यह उन्हें सही ढंग से संभालती है।

ऐसा करने के लिए, आप अपने सहकर्मी के घटक का उपयोग नहीं कर सकते हैं: इसके बजाय, मॉकिंग का उपयोग करें, अर्थात् , शेष एप्लिकेशन को "नकली" मॉड्यूल के साथ बदलें, जिसे आप परीक्षण ढांचे से नियंत्रित कर सकते हैं। आप वास्तव में यह कैसे करते हैं यह मॉड्यूल इंटरफ़ेस के तरीके पर निर्भर करता है; यह हार्ड-कोडित तर्कों के साथ अपने मॉड्यूल के तरीकों को कॉल करने के लिए पर्याप्त हो सकता है, और यह पूरे ढांचे को लिखने के रूप में जटिल हो सकता है जो परीक्षण मॉड्यूल के साथ अन्य मॉड्यूल के सार्वजनिक इंटरफेस को जोड़ता है।

हालांकि यह सिर्फ यूनिट टेस्ट का मामला है। आप एकीकरण परीक्षण भी चाहते हैं, जहां आप संगीत कार्यक्रम के सभी मॉड्यूल का परीक्षण करते हैं। फिर से, आप खुशहाल मामले और असफलताओं दोनों का परीक्षण करना चाहते हैं।

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

function test_ValidUser() {
    // set up mocking and fixtures
    userid = 23;
    db = new MockDB();
    db.fixedResult = { firstName: "John", lastName: "Doe" };
    db.expectedCall = { method: 'getUser', params: { userid: userid } };
    userController = new UserController(db);
    expectedResult = "John Doe";

    // run the actual test
    actualResult = userController.displayUserAsString(userid);

    // check assertions
    assertEquals(expectedResult, actualResult);
    db.assertExpectedCall();
}

और यहां बताया गया है कि आप उन फ़ील्ड्स के लिए कैसे परीक्षण करेंगे जो सही रूप से रिपोर्ट किए गए हैं :

function test_IncompleteUser() {
    // set up mocking and fixtures
    userid = 57;
    db = new MockDB();
    db.fixedResult = { firstName: "John", lastName: "NA" };
    db.expectedCall = { method: 'getUser', params: { userid: userid } };
    userController = new UserController(db);

    // let's say the user controller is specified to leave "NA" fields 
    // blank
    expectedResult = "John";

    // run the actual test
    actualResult = userController.displayUserAsString(userid);

    // check assertions
    assertEquals(expectedResult, actualResult);
    db.assertExpectedCall();
}

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

class MockDB {
    // ... snip
    function getUser(userid) {
        if (this.fixedException) {
            throw this.fixedException;
        }
        else {
            return this.fixedResult;
        }
    }
}

और फिर हमारा परीक्षण मामला इस तरह दिखता है:

function test_MisbehavingUser() {
    // set up mocking and fixtures
    userid = 57;
    db = new MockDB();
    db.fixedException = new SQLException("You have an error in your SQL syntax");
    db.expectedCall = { method: 'getUser', params: { userid: userid } };
    userController = new UserController(db);

    // run the actual test
    try {
        userController.displayUserAsString(userid);
    }
    catch (DatabaseException ex) {
        // This is good: our userController has caught the raw exception
        // from the database layer and wrapped it in a DatabaseException.
        return TEST_PASSED;
    }
    catch (Exception ex) {
        // This is not good: we have an exception, but it's the wrong kind.
        testLog.log("Found the wrong exception: " + ex);
        return TEST_FAILED;
    }
    // This is bad, too: either our mocking class didn't throw even when it
    // should have, or our userController swallowed the exception and
    // discarded it
    testLog.log("Expected an exception to be thrown, but nothing happened.");
    return TEST_FAILED;
}

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

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


क्या आपने प्रश्न के नीचे टिप्पणी पढ़ी है? ओपी ने "परीक्षण" लिखा, लेकिन उसका अर्थ "सत्यापन जांच" और / या "अपवाद से निपटने" के अर्थ में था
डॉक्टर ब्राउन

1
@ दोस्त: गलतफहमी के लिए खेद है, मैं वास्तव में अपवाद से निपटने का मतलब था .. वैसे भी पूर्ण उत्तर के लिए धन्यवाद, आखिरी पैराग्राफ वह है जो मैं देख रहा था।
रदुरंद

1

मेरे द्वारा कोड करने के लिए 3 मुख्य सिद्धांत हैं:

  • सूखी

  • चुम्मा

  • YAGNI

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

बेशक, भविष्य में कुछ बिंदु पर, आप कर सकते हैं अपने डेटाबेस replatform (ऐसा होता है) जो मामले में आप एक से अधिक जगह में कोड होने लाभप्रद होगा सोच सकते हैं। लेकिन ... आप ऐसी चीज़ के लिए कोडिंग कर रहे हैं जो हो ही नहीं सकता।

कोई भी अतिरिक्त कोड (भले ही वह कभी न बदले) ओवरहेड है क्योंकि इसे लिखने, पढ़ने, संग्रहीत करने और परीक्षण करने की आवश्यकता होगी।

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


1

आम आदमी के शब्दों में।

"डेटाबेस" या "एप्लिकेशन" जैसी कोई चीज नहीं है ।

  1. एक डेटाबेस का उपयोग एक से अधिक एप्लिकेशन द्वारा किया जा सकता है।
  2. एक अनुप्रयोग एक से अधिक डेटाबेस का उपयोग कर सकता है।
  3. डेटाबेस मॉडल को डेटा अखंडता को लागू करना चाहिए, जिसमें एक आवश्यक फ़ील्ड को सम्मिलित ऑपरेशन में शामिल नहीं किए जाने पर एक त्रुटि फेंकना शामिल है, जब तक कि तालिका परिभाषा में डिफ़ॉल्ट मान को परिभाषित नहीं किया जाता है। यह तब भी किया जाना चाहिए जब आप डेटाबेस को सीधे ऐप को दरकिनार कर पंक्ति में सम्मिलित करते हैं। डेटाबेस सिस्टम को आपके लिए करने दें।
  4. डेटाबेस को डेटा अखंडता की रक्षा करनी चाहिए और त्रुटियों को फेंकना चाहिए
  5. व्यावसायिक तर्क को उन त्रुटियों को पकड़ना होगा और प्रस्तुति परत के अपवादों को फेंकना होगा
  6. प्रस्तुति परत को इनपुट को मान्य करना होगा , अपवादों को संभालना होगा या उपयोगकर्ता को एक हैमस्टर दिखाना होगा।

फिर:

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