2011-01-12 19 views
5

मैं वर्तमान में Effective Perl Programming (2 संस्करण) पढ़ रहा हूं। मैं कोड के एक टुकड़े में आया हूं जिसे खराब लिखा गया था, लेकिन मुझे अभी तक समझ में नहीं आया कि इसके बारे में क्या बुरा है, या इसे कैसे सुधारना चाहिए। यह अच्छा होगा अगर कोई मुझे इस मामले की व्याख्या कर सके।डीबीआई को सीधे एक्सेस करने में क्या गलत है?

यहाँ प्रश्न में कोड है:

sub sum_values_per_key { 
    my ($class, $dsn, $user, $password, $parameters) = @_; 
    my %results; 

    my $dbh = 
    DBI->connect($dsn, $user, $password, $parameters); 

    my $sth = $dbh->prepare(
    'select key, calculate(value) from my_table'); 
    $sth->execute(); 

    # ... fill %results ... 

    $sth->finish(); 
    $dbh->disconnect(); 

    return \%results; 
} 

उदाहरण अपने कोड (पी। 324/325) के परीक्षण पर अध्याय से आता है। जिस वाक्य ने मुझे कोड को बेहतर बनाने के बारे में सोचते हुए छोड़ा है, वह निम्नलिखित है:

चूंकि कोड खराब लिखा गया था और सीधे डीबीआई तक पहुंचता है, तो आपको असली के लिए खड़े होने के लिए नकली डीबीआई ऑब्जेक्ट बनाना होगा चीज़।

शायद मुझे यह समझ में नहीं आया है कि पुस्तक अब तक मुझे सिखाने की कोशिश कर रही है, या मैंने उपर्युक्त कोड के बारे में क्या बुरा व्यवहार समझने के लिए प्रासंगिक अनुभाग छोड़ दिया है ... अच्छा, अग्रिम धन्यवाद तुम्हारी मदद के लिए!

+0

+1 मैं भी यह जवाब सुनना चाहता हूं। मैं यहां कुछ भी "गरीब" नहीं लग रहा हूं ... –

+0

अब तक दिए गए सभी उत्तरों ने इस मामले को बहुत अच्छी तरह से समझाया है, इसलिए आपके त्वरित प्रतिक्रियाओं के लिए सभी को धन्यवाद! मैं वास्तव में बहुत अंधेरा रहा हूं ... – canavanin

उत्तर

8

के बाद से अध्याय परीक्षण के बारे में है, इस पर विचार करें:

अपने समारोह का परीक्षण करते समय आपके पास (परोक्ष) परीक्षण DBI हैं। यही कारण है कि यह बुरा है।

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

+0

+1 यह बताता है कि उस अध्याय के बारे में क्या है। अचानक यह सवाल काफी सरल है। सोलिड लिंक के लिए –

4

डीबीआई का उपयोग करने में कुछ भी गलत नहीं है।

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

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

5

मुझे लगता है कि ब्रायन "खराब लिखित" कहने का प्रयास कर रहा था कि आपके पास व्यावसायिक तर्क और डेटा एक्सेस कोड (और डेटाबेस कनेक्शन मैकेनिक्स) के बीच अलगाव नहीं है।

कार्यों को लिखने का एक सही दृष्टिकोण यह है कि एक कार्य (या विधि) एक चीज, एक बार में 3 चीजें नहीं करनी चाहिए।

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

लेकिन डीबीआई जैसी जटिल-व्यवहार करने वाली वस्तु का मज़ाक करना बहुत सही और सही करने के लिए बहुत जटिल है।

यदि डेटाबेस पहुंच योग्य नहीं है तो क्या होगा? अगर ब्लॉकिंग हो तो क्या होगा? यदि आपकी क्वेरी में सिंटैक्स त्रुटि है तो क्या होगा? क्या होगा यदि क्वेरी निष्पादित करते समय डीबी कनेक्शन का समय समाप्त हो जाए? क्या होगा यदि ...

अच्छा परीक्षण कोड उन सभी त्रुटि स्थितियों और अन्य परीक्षणों का परीक्षण करता है।


एक और अधिक सही दृष्टिकोण (पैटर्न) कोड के लिए होगा:

my $dbh = set_up_dbh(); 
my $query = qq[select key, calculate(value) from my_table]; 
my $data = retrieve_data($dbh, $query); 
    # Now, we don't need to test setting up database connection AND data retrieval 
my $calc_results = calculate_results($data); 

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

4

sum_values_per_key नामक एक विधि को कुछ चाबियों के मानों को एकत्रित करने में रुचि होनी चाहिए, डेटा को संक्षेप में नहीं लाया जाना चाहिए।

यह एसओएलआईडी प्रोग्रामिंग के एस (एकल जिम्मेदारी सिद्धांत) को पूरा नहीं करता है। http://en.wikipedia.org/wiki/Solid_%28object-oriented_design%29

इसका मतलब यह है कि यह दोनों है:

  • नहीं पुन: प्रयोज्य आप विभिन्न स्रोत डेटा उपयोग करना चाहते हैं।
  • डेटाबेस कनेक्शन के बिना किसी वातावरण में परीक्षण करने में कठिनाई।
+0

धन्यवाद। – Dallaylaen

1

1) मान लीजिए कि आपके पास एक दर्जन विधियों के साथ प्रत्येक दर्जन वस्तुओं हैं। उन कार्यक्रमों में से बीस मुख्य कार्यक्रम के निष्पादन के दौरान बुलाए जाएंगे। अब आपने 20 डीबी कनेक्शन बनाए हैं जहां आपको केवल एक की आवश्यकता है।

2) मान लें कि आप मूल डीबीआई से खुश नहीं हैं और इसे मेरे :: डीबीआई के साथ बढ़ाया है। अब आपको 12 फाइलों में 144 कार्यों को फिर से लिखना होगा।

(अपाचे :: डीबीआई यहां एक उदाहरण हो सकता है)।

3) आपको उन 144 कार्यों में प्रत्येक कॉल में 3 पोजीशनल पैरामीटर लेना होगा। मानव मस्तिष्क एक समय में लगभग 7 वस्तुओं के साथ अच्छी तरह से काम करता है; आप बस अंतरिक्ष के लगभग आधा कम कर दिया है। यह कोड कम रखरखाव बनाता है।

संबंधित मुद्दे