डेटाबेस से संबंधित तरीकों को डिजाइन करना, जो वापस लौटना बेहतर है: सच / गलत या पंक्ति प्रभावित?


10

मेरे पास कुछ विधियाँ हैं जो डेटाबेस में कुछ डेटा चेंजिंग (इंसर्ट, अपडेट और डिलीट) करती हैं। ORM मैं इस प्रकार की विधि के लिए वापसी पंक्ति-प्रभावित int मानों का उपयोग कर रहा हूँ। ऑपरेशन की सफलता / विफलता की स्थिति को इंगित करने के लिए मुझे "मेरी विधि" के लिए क्या लौटना चाहिए?

उस कोड पर विचार करें जो वापस आ रहा है int:

A.1

public int myLowerLevelMethod(int id) {
    ...
    int affectedRows = myOrm.deleteById(id)
    ...

    return affectedRows;
}

फिर उपयोग:

.2

public void myOtherMethod() {
    ...
    int affectedRows = myLowerLevelMethod(id)

    if(affectedRows > 0) {
        // Success
    } else {
        // Fail
    }
}

बूलियन का उपयोग करने की तुलना करें:

B.1

public boolean myLowerLevelMethod(int id) {
    ...
    int affectedRows = myOrm.deleteById(id)
    ...

    return affectedRows > 0;
}

फिर उपयोग:

B.2

public void myOtherMethod() {
    ...
    boolean isSuccess = myLowerLevelMethod(id)

    if(isSuccess) {
        // Success
    } else {
        // Fail
    }
}

कौन सा (ए या बी) बेहतर है? या प्रत्येक के पेशेवरों / विपक्ष?


आपके "A.2" में। यदि शून्य पंक्तियाँ प्रभावित होती हैं, तो शून्य पंक्तियों को प्रभावित करने की आवश्यकता क्यों है? दूसरे शब्दों में, यदि डेटाबेस में कोई त्रुटि नहीं है, तो यह विफल क्यों है?
Jaydee

5
क्या "असफल" और "शून्य पंक्तियों से प्रभावित" के बीच एक शब्दार्थ अंतर है? जैसे, किसी ग्राहक के सभी आदेशों को हटाने के दौरान, "ग्राहक मौजूद नहीं है" और "ग्राहक के पास कोई आदेश नहीं है" के बीच अंतर होता है।
सेफालोपॉड

क्या आप शून्य पंक्तियों के साथ अप्रत्याशित रूप से हटाने पर विचार करते हैं? उस मामले में फेंक।
usr

@ एरियन मुझे लगता है कि मेरे लिए असली सवाल है। मुझे लगता है कि मैंने B को चुना, क्योंकि A के साथ, मेरे कोड में अब कुछ स्थानों में 0 और अन्य में -1 के लिए जाँच की जा रही है
Hoang Tran

जवाबों:


18

एक अन्य विकल्प बुनियादी प्रकार के बजाय परिणाम वस्तु को वापस करना है। उदाहरण के लिए:

OperationResult deleteResult = myOrm.deleteById(id);

if (deleteResult.isSuccess()) {
    // ....
}

इसके साथ, यदि किसी कारण से आपको प्रभावित पंक्तियों की संख्या को वापस करने की आवश्यकता है, तो आप ऑपरेशन में एक विधि जोड़ सकते हैं:

if (deleteResult.isSuccess()) {
    System.out.println("rows deleted: " + deleteResult.rowsAffected() );
}

यह डिज़ाइन आपके सिस्टम को मौजूदा कोड को संशोधित किए बिना नई कार्यक्षमता (प्रभावित पंक्तियों के बारे में जानने) को विकसित करने और शामिल करने की अनुमति देता है।


2
+1 "यह डिज़ाइन आपके सिस्टम को विकसित करने और मौजूदा कोड को संशोधित किए बिना नई कार्यक्षमता (प्रभावित पंक्तियों के बारे में जानने) को शामिल करने की अनुमति देता है" यह इस श्रेणी के प्रश्नों के बारे में सोचने का सही तरीका है।
सूचित

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

विशेष रूप से ORM का उपयोग करने वाली प्रणाली के लिए, मैं इस सर्वोत्तम अभ्यास को कहूंगा। प्रश्न में ORM में पहले से ही ऐसे परिणाम ऑब्जेक्ट प्रकार शामिल हो सकते हैं!
ब्रायन एस

केवल ओपी उदाहरण को देखते हुए, मैं केवल इतना ही सोच सकता हूं कि डिलीटबीड 2 किसी बिंदु पर 2 लौट आएगा :) इसलिए निश्चित रूप से एक कस्टम प्रकार, हां।
बहिश्त

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

12

प्रभावित पंक्तियों की संख्या वापस करना बेहतर है क्योंकि यह ऑपरेशन कैसे आगे बढ़ता है इसके बारे में अतिरिक्त जानकारी देता है।

कोई भी प्रोग्रामर आपको दोषी नहीं ठहराएगा क्योंकि ऑपरेशन के दौरान उसे कुछ बदलाव मिले, यह जांचने के लिए उसे लिखना होगा:

if(affectedRows > 0) {
    // success
} else {
    // fail
}

लेकिन वे आपको दोषी ठहराएंगे जब उन्हें प्रभावित पंक्तियों की संख्या जाननी होगी और उन्हें एहसास होगा कि उस संख्या को प्राप्त करने की कोई विधि नहीं है।

BTW: यदि "विफलता" से आपका मतलब है कि एक वाक्यात्मक क्वेरी त्रुटि (जिस स्थिति में प्रभावित पंक्तियों की संख्या स्पष्ट रूप से 0 है) तो अपवाद फेंकना अधिक उचित होगा।


4
-1 जिस वजह से आपने दिया। अतिरिक्त जानकारी देना हमेशा एक अच्छा विचार नहीं है। अक्सर, बेहतर डिजाइन कॉलर को संचार करने के लिए प्रेरित करता है कि उसे क्या चाहिए, और अधिक कुछ नहीं।
Arseni Mourzenko

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

@PTwr: इस तथ्य से निपटने के लिए कि विधि बहुत अधिक जानकारी लौटा रही है, आप एक अधिभार बनाने का सुझाव देते हैं? यह सही नहीं लगता। जैसा कि "शून्य असत्य है, अ-शून्य सत्य है", यह मेरी टिप्पणी का बिंदु नहीं है, और कुछ भाषाओं में एक बुरा व्यवहार है।
आर्सेनी मूरज़ेंको

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

4
आपको हमेशा प्रभावित पंक्तियों की संख्या यहां लौटानी चाहिए !!! चूँकि आप संभवतः यह नहीं जान सकते कि पंक्तियों की संख्या = 0 विफलता है या यदि पंक्तियों की संख्या = 3 एक सफलता है? अगर कोई 3 पंक्तियों को सम्मिलित करना चाहता है और केवल 2 सम्मिलित करता है, तो आप सही लौटाएंगे, लेकिन यह सही नहीं है! और अगर कोई चाहे तो update t set category = 'default' where category IS NULL0 प्रभावित पंक्तियों को भी सफल बना सकता है, क्योंकि अब श्रेणी के बिना कोई वस्तु नहीं है, भले ही कोई पंक्तियाँ प्रभावित न हों!
फाल्को

10

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

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

सवाल यह है कि सफलता / त्रुटि का संकेत कैसे दिया जाए। इस मामले में यह अपवाद को फेंककर विफलता का संकेत देने के लिए पर्याप्त है और सफलता पर कुछ भी नहीं लौटाता है। मुझे उपयोगकर्ता की आवश्यकता से अधिक प्रदान क्यों करना है?

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


4
-1 कोई भी ऐसा क्यों नहीं लौटाया जाए जहां आप कुछ वापस कर सकते हैं, कोई नकारात्मक पक्ष प्रभाव के साथ, जो अतिरिक्त परिचालन संदर्भ प्रदान करता है?
FreeAsInBeer

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

1
खैर, उपयोगकर्ता को वास्तव में कौन से डेटा की आवश्यकता है? सवाल यह है कि सफलता / त्रुटि का संकेत कैसे दिया जाए। इस मामले में यह अपवाद को फेंककर विफलता का संकेत देने के लिए पर्याप्त है और सफलता पर कुछ भी नहीं लौटाता है। मुझे उपयोगकर्ता की आवश्यकता से अधिक प्रदान क्यों करना है?
प्रिटोरर

4
@proskor: अपवाद असाधारण मामलों के लिए हैं। इस परिदृश्य में "विफलता" एक अपेक्षित परिणाम हो सकता है। हर तरह से, इसे एक संभावित विकल्प के रूप में आगे रखें, लेकिन सिफारिश करने के लिए यहां पर्याप्त जानकारी नहीं है।
निक बार्न्स

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

2

"क्या यह इससे बेहतर है?" जब दो विकल्प एक ही काम नहीं करते हैं तो एक उपयोगी प्रश्न नहीं है।

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

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


मैं इस बात से सहमत हूं कि यह ऐप की आवश्यकताओं पर निर्भर करता है। हालाँकि ऐसा लगता है कि इस तरह की स्थिति बहुत अनोखी नहीं है, और मैं एक चांदी की गोली की तलाश नहीं कर रहा हूँ, लेकिन बस उसी / समान चीज़ के साथ काम करने का अन्य अनुभव (शायद सवाल थोड़ा भ्रामक है, मुझे A के अलावा अन्य सुझाव पसंद हैं / बी)
होआंग ट्रॅन

1

पोषणीय सॉफ्टवेयर डिजाइन में सबसे महत्वपूर्ण सिद्धांतों में से दो हैं KISS और YAGNI

  • KISS : यह सरल रखें, बेवकूफ
  • YAGNI : आपको इसकी आवश्यकता नहीं है

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

किसी भी जटिलता को आप एक कार्यक्रम में जोड़ते हैं, एक लागत पर आता है, जो लंबे समय तक भुगतान किया जाता है। कार्यक्रम को पढ़ना और अधिक जटिल हो जाता है, बदलने के लिए और अधिक जटिल, और कीड़े के लिए आसान हो जाता है। "बस मामले में" चीजों को जोड़ने के जाल के लिए मत गिरो। यह सुरक्षा की झूठी भावना है।

आप शायद ही कभी पहली बार कोई कोड प्राप्त करने जा रहे हों। परिवर्तन अपरिहार्य हैं; भविष्य के अज्ञात आकस्मिकताओं के लिए रक्षात्मक रूप से तैयार करने के लिए सट्टा तर्क में जोड़ना वास्तव में आपको अपने कोड को रीफ़्रैक्टर करने से नहीं बचाएगा जब भविष्य आपकी अपेक्षा से अलग हो जाएगा। अनावश्यक / आकस्मिक तर्क पर निर्भरता गायब कार्यक्षमता में जोड़ने के लिए बाद में रिफैक्टिंग की तुलना में एक स्थिरता की समस्या का अधिक है।

इस प्रकार, चूंकि यह प्रतीत होता है कि आपके सभी कार्यक्रम अब के लिए जानना चाहते हैं कि ऑपरेशन सफल हुआ या असफल, आपका प्रस्तावित समाधान बी (एक एकल बूलियन लौटाएं) सही दृष्टिकोण है। आवश्यकता बदल जाने पर आप इसे बाद में कभी भी रिफलेक्टर कर सकते हैं। यह समाधान सरल है और सबसे कम जटिलता (चुंबन) है और सिर्फ तुम क्या जरूरत है और ज्यादा कुछ नहीं (YAGNI)।


-1

पूरी पंक्तियों या एक त्रुटि स्थिति

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

दूसरी ओर, यदि आप दिए गए डेटा की जरूरत नहीं है, तो आप भी प्रभावित पंक्ति संख्या, की जरूरत नहीं है यह 0. का परिणाम के लिए उपयोगी नहीं है के बाद से अगर कोई ग़लती ना हो, तो तुम वापस जाने के लिए की जरूरत है कि किस तरह की गलती हुई, एक तरह से आपके प्रोजेक्ट एरर हैंडलिंग सिद्धांतों (अपवाद, संख्यात्मक त्रुटि कोड, जो भी हो) के अनुरूप; लेकिन वैध प्रश्न हैं जो 0 पंक्तियों को सही ढंग से प्रभावित करेंगे (अर्थात "वास्तव में कोई भी नहीं हैं तो" सभी समाप्त आदेश हटाएं ")।

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