टेस्टेबल कोड लिखना बनाम सट्टा सामान्यता से बचना


11

मैं आज सुबह कुछ ब्लॉग पोस्ट पढ़ रहा था, और इस पर ठोकर खाई :

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

यह मेरे लिए समझ में आता है, जैसा कि एक इंटरफ़ेस को लागू करना जटिलता जोड़ता है और, यदि केवल एक कार्यान्वयन होता है, तो कोई यह तर्क दे सकता है कि यह अनावश्यक जटिलता जोड़ता है। लेखन कोड जो कि अधिक सारगर्भित होने की आवश्यकता है, उसे अक्सर कोड गंध माना जाता है जिसे "सट्टा सामान्यता" (पोस्ट में उल्लिखित) भी कहा जाता है।

लेकिन, अगर मैं टीडीडी का अनुसरण कर रहा हूं, तो मैं (आसानी से) उस सट्टा व्यापकता के बिना टेस्ट डबल्स नहीं बना सकता हूं, चाहे वह इंटरफ़ेस कार्यान्वयन के रूप में हो या हमारे अन्य पॉलीमॉर्फिक विकल्प के रूप में, कक्षा को अंतर्निहित और इसके तरीकों को आभासी बना सकता है।

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

मैं इस मामले पर अन्य लोगों को पढ़ने के लिए उत्सुक हूं - आपकी राय के लिए अग्रिम धन्यवाद।


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

7
हम गतिशील रूप से टाइप की गई भाषाओं के उपयोगकर्ताओं को आपके द्वारा टाइप की गई भाषाओं में आपके द्वारा डाली गई जंजीरों पर आपके हंसने पर हँसाते हैं। यह एक ऐसी चीज है जो गतिशील रूप से टाइप की गई भाषाओं में इकाई परीक्षण को आसान बनाती है, मुझे परीक्षण उद्देश्यों के लिए किसी वस्तु को घटाने के लिए एक इंटरफ़ेस विकसित करने की आवश्यकता नहीं है।
विंस्टन एवरर्ट

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

@InstonEwert डायनामिक टाइपिंग का एक दिलचस्प लाभ है जिसे मैंने पहले किसी के रूप में नहीं माना था, जैसा कि आप बताते हैं, आमतौर पर गतिशील रूप से टाइप की गई भाषाओं में काम नहीं करता है।
एरिक डायट्रिच

@CodeInChaos मैंने इस प्रश्न के प्रयोजनों के लिए भेद नहीं माना था, हालांकि यह एक उचित अंतर है। इस मामले में, हम केवल एक (वर्तमान) कार्यान्वयन के साथ सेवा / रूपरेखा कक्षाओं के बारे में सोच सकते हैं। मान लीजिए कि मेरे पास एक डेटाबेस है जिसे मैं DAO के साथ एक्सेस करता हूं। जब तक मेरे पास एक माध्यमिक दृढ़ता मॉडल नहीं है, क्या मुझे DAO को इंटरफ़ेस नहीं करना चाहिए? (ऐसा लगता है कि ब्लॉग पोस्ट लेखक का क्या अर्थ है)
एरिक डायट्रिच

जवाबों:


14

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


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

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

मैं यह भी जोड़ूंगा, जब आप परीक्षणों में इंटरफेस के आधार पर हैं, तो सामान्यता अब सट्टा नहीं है
पीट

"ऐसा नहीं करना" (इंटरफेस का उपयोग करना) स्वचालित रूप से आपकी कक्षाओं में कसकर-युग्मित होने का परिणाम नहीं देता है। यह सिर्फ नहीं है। उदाहरण के लिए .NET फ्रेमवर्क में एक Streamवर्ग है, लेकिन कोई तंग-युग्मन नहीं है।
ल्यूक पुप्लेट

3

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

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

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

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

जहां मुझे कोई भी "अप्रतिबंधित" कोड मिलता है, मैं देखता हूं कि क्या मैं चीजों को अधिक परीक्षण योग्य बनाने के लिए रिफ्लेक्टर कर सकता हूं। जहाँ आपके पास बहुत सारे निजी कोड होते हैं जो पर्दे के सामान के पीछे छिपे होते हैं, अक्सर आपको नई कक्षाएं मिलेंगी जो टूटने की प्रतीक्षा कर रही हैं। इन वर्गों को आंतरिक रूप से इस्तेमाल किया जा सकता है, लेकिन अक्सर कम निजी व्यवहार के साथ स्वतंत्र रूप से परीक्षण किया जा सकता है, और अक्सर बाद में पहुंच और जटिलता की कम परतें। हालांकि मैं इससे बचने के लिए ध्यान रखता हूं कि इसमें निर्मित टेस्ट कोड के साथ उत्पादन कोड लिख रहा है। यह " टेस्ट लग्स " बनाने के लिए आकर्षक हो सकता है if testing then ..., जिसके परिणामस्वरूप ऐसी भयावहता शामिल है , जो एक परीक्षण समस्या को पूरी तरह से विघटित और अपूर्ण हल नहीं होने का संकेत देती है।

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


1

क्या आपके द्वारा उपयोग की जाने वाली भाषा में परीक्षण के लिए एक वस्तु "मॉक" करने का एक तरीका है? यदि ऐसा है तो ये कष्टप्रद इंटरफेस दूर जा सकते हैं।

एक अलग नोट पर एक SimpleInterface और एक एकमात्र ComplexThing के कारण हो सकते हैं जो इसे लागू करते हैं। वहाँ ComplexThing के टुकड़े हो सकते हैं जो आप SimpleInterface उपयोगकर्ता के लिए सुलभ नहीं चाहते हैं। यह हमेशा एक अति-विपुल OO-ish कोडर के कारण नहीं होता है।

मैं अब दूर जाऊंगा और सभी को इस तथ्य पर कूदने दूंगा कि यह कोड उनके लिए "बुरी गंध" देता है।


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

0

मैं दो भागों में उत्तर दूंगा:

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

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


0

मैंने कई फायदे देखे हैं क्योंकि मैंने बहुरूपता से परे एक अंतरफलक के लिए अधिक प्रोग्रामिंग शुरू कर दिया है।

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

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

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

सभी के लिए, मेरा मानना ​​है कि इसने मुझे उच्च गुणवत्ता कोड लिखने में मदद की है और लाभ किसी भी परिणाम से आगे निकल गए हैं।

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