डाईएडिक फ़ंक्शन के साथ आने वाली समस्याओं को हल करना (अपेक्षित, वास्तविक)


10

काउबॉय कोडिंग के वर्षों के बाद, मैंने अच्छी गुणवत्ता कोड लिखने के तरीके पर एक किताब लेने का फैसला किया। मैं रॉबर्ट सेसिल मार्टिन द्वारा क्लीन कोड पढ़ रहा हूं। अध्याय 3 (फ़ंक्शन) में डायडिक कार्यों पर एक अनुभाग है। यहाँ पुस्तक से एक अंश है।

यहां तक ​​कि स्पष्ट dyadic कार्यों की तरह assertEquals(expected, actual)समस्याग्रस्त हैं। कितनी बार आपने वास्तविक को रखा है जहाँ अपेक्षित होना चाहिए? दोनों तर्कों में कोई स्वाभाविक आदेश नहीं है। अपेक्षित, वास्तविक आदेश एक सम्मेलन है जिसे सीखने के लिए अभ्यास की आवश्यकता होती है।

लेखक एक सम्मोहक बिंदु बनाता है। मैं मशीन लर्निंग में काम करता हूं और हर समय इस पर आता हूं। उदाहरण के लिए, स्केलेर लाइब्रेरी में सभी मीट्रिक फ़ंक्शंस (संभवतः क्षेत्र में सबसे अधिक इस्तेमाल किया जाने वाला पायथन लाइब्रेरी) आपको इनपुट के क्रम से सावधान रहने की आवश्यकता है। एक उदाहरण के रूप में sklearn.metrics.homogeneity_score इनपुट labels_trueऔर के रूप में लेता है labels_pred। यह फ़ंक्शन बहुत प्रासंगिक नहीं है, जो प्रासंगिक है वह यह है कि यदि आप इनपुट के क्रम को बदलते हैं तो कोई त्रुटि नहीं होगी। वास्तव में आदानों को बदलना पुस्तकालय में एक अन्य फ़ंक्शन का उपयोग करने के बराबर है ।

हालांकि इस तरह के कार्यों के लिए एक समझदार तय कहने के लिए पुस्तक पर नहीं जाती है assertEquals। मैं उन assertEqualsकार्यों के लिए या उनके बारे में ठीक नहीं सोच सकता, जो अक्सर ऊपर वर्णित एक के समान हैं। इस मुद्दे को हल करने के लिए अच्छे अभ्यास क्या हैं?

जवाबों:


11

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

पैरामीटर ऑर्डर के बारे में किसी भी भ्रम को रोकने के लिए भाषा स्तर के तरीके हैं: नामित तर्क। यह दुर्भाग्य से कई भाषाओं में समर्थित नहीं है जैसे कि सी-स्टाइल सिंटैक्स जैसे जावा या सी ++। लेकिन पायथन में, हर तर्क एक नामित तर्क हो सकता है। एक फ़ंक्शन def foo(a, b)को कॉल करने के बजाय foo(1, 2), हम कर सकते हैं foo(a=1, b=2)। C # जैसी कई आधुनिक भाषाओं में समान सिंटैक्स है। स्मॉलटॉक भाषा परिवार ने तर्कों का नाम लिया है: कोई भी स्थिति नहीं है और सब कुछ नाम दिया गया है। यह कोड को जन्म दे सकता है जो प्राकृतिक भाषा के बहुत करीब से पढ़ता है।

एक अधिक व्यावहारिक विकल्प एपीआई बनाने के लिए है जो नामित तर्कों का अनुकरण करता है। ये धाराप्रवाह एपीआई, या सहायक कार्य हो सकते हैं जो एक प्राकृतिक प्रवाह बनाते हैं। assertEquals(actual, expected)नाम भ्रमित कर रहा है। कुछ विकल्प जो मैंने देखे हैं:

  • assertThat(actual, is(equalTo(expected))): सहायक प्रकार में कुछ तर्कों को लपेटकर, रैपिंग फ़ंक्शन प्रभावी रूप से पैरामीटर नामों के रूप में कार्य करता है। इकाई परीक्षण के कथनों के विशिष्ट मामले में, इस तकनीक का उपयोग हैमरेस्ट मैचर्स द्वारा एक एक्स्टेंसिबल और कंपोजिटेबल दावे प्रणाली प्रदान करने के लिए किया जाता है। यहाँ नुकसान यह है कि आपको बहुत सारे घोंसले मिलते हैं, और बहुत सारे सहायक कार्य करने की आवश्यकता होती है। यह सी ++ में मेरी तकनीक है।

  • expect(actual).to.be(expected): एक धाराप्रवाह एपीआई जहां आप स्ट्रिंग फ़ंक्शन एक साथ कॉल करते हैं। हालांकि यह अतिरिक्त घोंसले के शिकार से बचता है, लेकिन यह बहुत अधिक नहीं है। जबकि मुझे लगता है कि धाराप्रवाह एपीआई बहुत अच्छी तरह से पढ़ते हैं, एक अच्छा धाराप्रवाह एपीआई डिजाइनिंग मेरे अनुभव में बहुत प्रयास करता है, क्योंकि आपको कॉल श्रृंखला में गैर-टर्मिनल राज्यों के लिए अतिरिक्त कक्षाएं लागू करने की आवश्यकता है। यह प्रयास केवल स्वतः पूर्ण आईडी के संदर्भ में भुगतान करता है जो अगली अनुमत विधि कॉल का सुझाव दे सकता है।


4

इस समस्या से बचने के लिए कई तरीके हैं। एक जो आपको कॉल करने के तरीके को बदलने के लिए मजबूर नहीं करता है:

बजाय

assertEquals( 42, meaningOfLife() ); 

उपयोग

expected = 42;
actual = meaningOfLife();
assertEquals(expected, actual);

यह सम्मेलन को खुले में बाहर करने के लिए मजबूर करता है जहां उन्हें स्विच करना आसान होता है। यकीन है कि यह लिखना इतना आसान नहीं है लेकिन पढ़ना आसान है।

यदि आप कॉल की जा रही विधि को बदल सकते हैं, तो आप टाइपिंग सिस्टम का उपयोग कर सकते हैं उपयोग करने के लिए मजबूर करना आसान है।

assertThat( meaningOfLife(), is(42) );

कुछ भाषाओं ने आपको इससे बचने दिया क्योंकि उन्होंने मापदंडों का नाम दिया है:

assertEquals( expected=42, actual=meaningOfLife() );

अन्य लोग ऐसा नहीं करते हैं:

assertEquals().expected(42).actual( meaningOfLife() );

आप जो कुछ भी करते हैं वह एक ऐसा तरीका है जो स्पष्ट करता है जो पढ़ते समय सही है। मुझे अनुमान नहीं है कि सम्मेलन क्या है। मुझें दिखाओ।

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