मैं कोड अनुबंधों का उपयोग क्यों करूंगा


26

मैंने हाल ही में कोड अनुबंधों के लिए Microsoft के ढांचे पर ठोकर खाई है।

मैंने कुछ दस्तावेज़ीकरण पढ़ा और खुद को लगातार पूछते हुए पाया: "मैं कभी भी ऐसा क्यों करना चाहता हूं, क्योंकि यह अक्सर एक स्थिर विश्लेषण नहीं कर सकता है।"

अब, मेरे पास एक प्रकार की रक्षात्मक प्रोग्रामिंग शैली पहले से ही है, इस तरह के अपवादों की रखवाली के साथ:

if(var == null) { throw new NullArgumentException(); }

मैं NullObject पैटर्न एक बहुत का उपयोग कर रहा हूँ और शायद ही कभी कोई समस्या है। इसमें यूनिट टेस्ट जोड़ें और आप सभी सेट अप हैं।

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

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



1
आप ऐसा क्यों कहते हैं "यह अक्सर स्थिर विश्लेषण नहीं कर सकता है"? मैंने सोचा था कि इस परियोजना के बिंदुओं में से एक था (जैसा कि सिर्फ एसेर्ट्स या रक्षात्मक अपवाद फेंकने का उपयोग करके विरोध किया गया है)?
कार्सन 63000

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

@ फाल्कन: अजीब तरह से, मेरा अनुभव पूरी तरह से अलग है। स्थैतिक विश्लेषण त्रुटिपूर्ण रूप से नहीं, बल्कि बहुत अच्छी तरह से काम करता है, और मुझे शायद ही कभी अनावश्यक चेतावनी दिखाई देती है, तब भी जब चेतावनी स्तर 4 (उच्चतम) पर काम कर रहे हों।
आर्सेनी मूरज़ेंको

मुझे लगता है कि मुझे यह जानने की कोशिश करनी होगी कि यह कैसे व्यवहार करता है।
फाल्कन

जवाबों:


42

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

लेकिन मूल तर्क संकलन समय पर उन मुद्दों को खोजने और ठीक करने की क्षमता होगी जो अन्यथा उत्पादन में फिसल गए होंगे।

संविदा बनाम गार्ड

यहां तक ​​कि गार्ड और अपवादों के साथ आप अभी भी इस मुद्दे के साथ सामना कर रहे हैं कि सिस्टम कुछ उदाहरण में यह इच्छित कार्य करने में विफल हो जाएगा। संभवतः एक ऐसा उदाहरण जो विफल होने के लिए काफी महत्वपूर्ण और महंगा होगा।

संविदा बनाम यूनिट परीक्षण

इस पर सामान्य तर्क यह है कि परीक्षण कीड़े की उपस्थिति को साबित करते हैं, जबकि प्रकार (अनुबंध) अनुपस्थिति को साबित करते हैं। F.ex. एक प्रकार का उपयोग करके आप जानते हैं कि कार्यक्रम में कोई भी पथ संभवतः अमान्य इनपुट की आपूर्ति नहीं कर सकता है, जबकि एक परीक्षण केवल आपको बता सकता है कि कवर किए गए पथ ने सही इनपुट की आपूर्ति की है।

संविदा बनाम अशक्त वस्तु पैटर्न

अब यह कम से कम एक ही बॉल पार्क में है। स्काला और हास्केल जैसी भाषाओं को कार्यक्रमों से पूरी तरह से अशक्त संदर्भों को समाप्त करने के इस दृष्टिकोण के साथ बड़ी सफलता मिली है। (यहां तक ​​कि अगर स्काला औपचारिक रूप से नल को अनुमति देता है तो सम्मेलन कभी भी उनका उपयोग नहीं करता है)

यदि आप पहले से ही एनआरई को खत्म करने के लिए इस पैटर्न को नियोजित करते हैं, तो आपने मूल रूप से रनटाइम विफलताओं का सबसे बड़ा स्रोत हटा दिया है, मूल रूप से जिस तरह से अनुबंध आपको इसे करने की अनुमति देता है।

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

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

परंतु...

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


6
यह प्रोग्रामर्स पर एक महान पहला जवाब है। खुशी है कि समुदाय में आपकी भागीदारी है।

13

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

तो यहाँ यह आता है, पहला लाभ:

लाभ 1: स्थैतिक विश्लेषण

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

लाभ 2: हमेशा की तरह अप टू डेट डॉक्यूमेंटेशन

कोड अनुबंध भी एक प्रकार का प्रलेखन प्रदान करते हैं जो हमेशा अद्यतित होता है। यदि विधि की XML टिप्पणी SetProductPrice(int newPrice)बताती है कि newPriceशून्य से बेहतर या बराबर होना चाहिए, तो आप उम्मीद कर सकते हैं कि दस्तावेज़ अद्यतित है, लेकिन आपको यह भी पता चल सकता है कि किसी ने विधि को बदल दिया है, जो कि newPrice = 0फेंकता है ArgumentOutOfRangeException, लेकिन कभी भी संबंधित दस्तावेज को नहीं बदला। कोड अनुबंधों और स्वयं कोड के बीच संबंध को देखते हुए, आपके पास आउट-ऑफ-सिंक प्रलेखन समस्या नहीं है।

कोड अनुबंधों द्वारा प्रदान किए गए दस्तावेज़ीकरण का प्रकार भी एक तरह से कीमती है, अक्सर, एक्सएमएल टिप्पणियां स्वीकार्य मूल्यों को अच्छी तरह से नहीं समझाती हैं। कितनी बार मैं सोच अगर था nullया string.Emptyया \r\nएक विधि के लिए एक अधिकृत मूल्य है, और XML टिप्पणी है कि पर चुप थे!

अंत में, कोड अनुबंध के बिना, कोड के बहुत सारे टुकड़े इस तरह हैं:

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

कोड अनुबंधों के साथ, यह बन जाता है:

शीर्षक तर्क 0.500 की लंबाई के साथ एक गैर-शून्य स्ट्रिंग हो सकता है। पूर्णांक जो निम्न प्रकार है वह एक सकारात्मक मान है, जो केवल तब ही शून्य हो सकता है जब स्ट्रिंग खाली हो। अंत में, मैं एक IDefinitionवस्तु लौटाऊंगा, कभी अशक्त नहीं।

लाभ 3: इंटरफेस के अनुबंध

एक तीसरा लाभ यह है कि कोड अनुबंध इंटरफेस को सशक्त बनाता है। मान लीजिए कि आपके पास कुछ ऐसा है:

public interface ICommittable
{
    public ICollection<AtomicChange> PendingChanges { get; }

    public void CommitChanges();

    ...
}

केवल असेन्ट्स और अपवादों का उपयोग करके आप कैसे गारंटी लेंगे कि खाली न CommitChangesहोने पर ही कॉल किया जा सकता PendingChangesहै? आप कैसे गारंटी देंगे कि PendingChangesकभी नहीं null?

लाभ 4: एक विधि के परिणामों को लागू करें

अंत में, चौथा लाभ Contract.Ensureपरिणामों में सक्षम होना है । क्या होगा यदि, एक विधि लिखते समय जो पूर्णांक लौटाता है, मैं यह सुनिश्चित करना चाहता हूं कि मूल्य कभी भी हीन या शून्य के बराबर नहीं है? कई डेवलपर्स से बहुत सारे परिवर्तनों से पीड़ित होने के बाद, पांच साल बाद सहित? जैसे ही एक विधि में कई वापसी बिंदु होते हैं, उसके Assertलिए एक रखरखाव दुःस्वप्न बन जाता है।


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

डायनेमिक टाइपिंग और स्टैटिक टाइपिंग के बीच अंतर कॉन्ट्रैक्ट द्वारा साधारण प्रोग्रामिंग और प्रोग्रामिंग के बीच अंतर के बेहद करीब है।


3

मुझे पता है कि इस सवाल में थोड़ी देर है, लेकिन कोड कॉन्ट्रैक्ट्स के लिए एक और लाभ है जो उल्लेख करता है

ठेके को विधि से बाहर की जाँच की जाती है

जब हमारे पास हमारे तरीके के अंदर गार्ड की स्थितियां होती हैं, तो यह वह जगह होती है, जहां चेकिंग होती है और जहां गलतियां बताई जाती हैं। फिर हमें यह पता लगाने के लिए स्टैक ट्रेस की पड़ताल करनी पड़ सकती है कि त्रुटि का वास्तविक स्रोत कहां है।

कोड कॉन्ट्रैक्ट विधि के भीतर स्थित होते हैं, लेकिन जब उस विधि को कॉल करने के लिए कुछ भी करने का प्रयास किया जाता है, तो प्रीडोंडिशन विधि के बाहर की जाँच की जाती है। अनुबंध विधि का हिस्सा बन जाते हैं और निर्धारित करते हैं कि यह कहा जा सकता है या नहीं। इसका मतलब है कि हमें समस्या के वास्तविक स्रोत के काफी करीब एक त्रुटि मिली है।

यदि आपके पास एक अनुबंधित संरक्षित तरीका है जिसे कई स्थानों के लिए कहा जाता है, तो यह एक वास्तविक लाभ हो सकता है।


2

दो चीजें वास्तव में:

  1. टूलींग समर्थन, वी.एस. इंटेलीजेंस के अलावा अनुबंध डेटा बना सकता है ताकि यह ऑटो की पूरी मदद का हिस्सा हो।
  2. जब एक उपवर्ग एक ऐसी विधि को ओवरराइड करता है जिसे आप अपने सभी चेक खो देते हैं (जो कि तब भी मान्य होना चाहिए यदि आप एलएसपी का पालन करते हैं) अनुबंधों के साथ वे अपने बच्चे की कक्षाओं का स्वचालित रूप से पालन करते हैं।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.