एक प्रोग्रामर को संदर्भित पारदर्शिता के लाभ क्या हैं?


18

प्रोग्रामिंग में, संदर्भात्मक पारदर्शिता के क्या लाभ हैं ?

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

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

नोट: यह क्या प्रासंगिक पारदर्शिता की नकल नहीं है ? उत्तरार्द्ध आरटी क्या है के विषय को संबोधित करता है, जबकि यह प्रश्न इसके लाभों को स्वीकार करता है (जो इतना सहज नहीं हो सकता है)।




3
रेफ़रेंशियल ट्रांसपेरसी आपको समतुल्य तर्क का उपयोग करने की अनुमति देती है: 1) कोड के गुण और 2) प्रोग्राम लिखें । हास्केल के बारे में कुछ किताबें हैं जहां लेखकों को आपको कुछ समीकरणों से कैसे शुरू करना चाहिए, जिन्हें आप फुलफिल के लिए एक फ़ंक्शन चाहते हैं और केवल समान तर्क का उपयोग करके आप अंत में उक्त फ़ंक्शन का कार्यान्वयन प्राप्त करते हैं, जो कि, इसलिए निश्चित रूप से सही है। अब "दिन-प्रतिदिन की" प्रोग्रामिंग में इसे कितना लागू किया जा सकता है यह शायद संदर्भ पर निर्भर करता है ...
बाकुरिउ नो

2
@ err क्या आपको कोड पसंद है जो रिफ्लेक्टर के लिए आसान है क्योंकि आप जानते हैं कि क्या किसी फ़ंक्शन को दो बार कॉल करना एक वैरिएबल में इसके मूल्य को स्टोर करने के समान है, फिर कहा गया वेरिएबल दो बार उपयोग करना? क्या आप कहेंगे कि आपके दिन प्रतिदिन की प्रोग्रामिंग के लिए यह एक लाभ है?
एंड्रेस एफ।

लाभ यह है कि आपको रेफरेंसियल नॉनट्रांसपैरेंसी के बारे में सोचने में समय बर्बाद करने की आवश्यकता नहीं है। चर जैसे कि चर के लाभ कैसे हैं कि आपको रजिस्टर आवंटन के बारे में सोचने में समय बर्बाद करने की आवश्यकता नहीं है।
23:25 पर user253751

जवाबों:


37

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

computeProductPriceविधि का उदाहरण लें ।

एक शुद्ध विधि आपको एक उत्पाद की मात्रा, एक मुद्रा आदि के लिए पूछेगा। आप जानते हैं कि जब भी विधि को समान तर्कों के साथ कहा जाता है, तो यह हमेशा एक ही परिणाम देगा।

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

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

उदाहरण

कल्पना कीजिए कि ढांचे में एक विधि है जो एक संख्या को पार करती है:

decimal math.parse(string t)

इसमें संदर्भात्मक पारदर्शिता नहीं है, क्योंकि यह इस पर निर्भर करता है:

  • पर्यावरण चर जो संख्या प्रणाली को निर्दिष्ट करता है, वह है बेस 10 या कुछ और।

  • mathलाइब्रेरी के भीतर चर जो पार्स करने के लिए संख्याओं की शुद्धता को निर्दिष्ट करता है। तो, मान के साथ 1, स्ट्रिंग "12.3456"को पार्स करना होगा 12.3

  • संस्कृति, जो अपेक्षित प्रारूपण को परिभाषित करती है। उदाहरण के लिए, साथ fr-FR, पार्सिंग "12.345"देगा 12345, क्योंकि अलगाव चरित्र होना चाहिए ,, नहीं.

कल्पना करें कि इस तरह की विधि के साथ काम करना कितना आसान या कठिन होगा। एक ही इनपुट के साथ, आप उस समय के आधार पर अलग-अलग परिणाम प्राप्त कर सकते हैं जब आप विधि को कॉल करते हैं, क्योंकि कुछ, कहीं न कहीं पर्यावरण चर को बदल देता है या संस्कृति को बदल देता है या एक अलग परिशुद्धता सेट करता है। विधि का गैर-निर्धारक चरित्र अधिक कीड़े और अधिक डीबगिंग दुःस्वप्न को जन्म देगा। कुछ समानांतर कोड को पार्स करने के बाद से एक उत्तर के रूप में कॉलिंग math.parse("12345")और प्राप्त करना 5349अच्छा नहीं है।

इस स्पष्ट रूप से टूटी हुई विधि को कैसे ठीक करें? रेफरेंशियल ट्रांसपेरेंसी की शुरुआत करके। दूसरे शब्दों में, वैश्विक स्थिति से छुटकारा पाने के लिए, और विधि के मापदंडों के लिए सब कुछ आगे बढ़ रहा है:

decimal math.parse(string t, base=10, precision=20, culture=cultures.en_us)

अब जब कि विधि शुद्ध है, तो आप जानते हैं कि जब आप विधि को कॉल करते हैं, तो कोई बात नहीं, यह हमेशा समान तर्कों के लिए एक ही परिणाम देगा।


4
बस एक परिशिष्ट: संदर्भात्मक पारदर्शिता भाषा में सभी अभिव्यक्तियों पर लागू होती है, न कि केवल कार्यों के लिए।
18

3
ध्यान दें कि आप कितनी पारदर्शी हो सकती हैं, इसकी सीमाएँ हैं। packet = socket.recv()संदर्भ को पारदर्शी बनाने के बजाय फ़ंक्शन के बिंदु को पराजित करता है।
मार्क

1
संस्कृति होना चाहिए। जब तक आप गलती से सॉफ्टवेयर बनाना चाहते हैं जो केवल यूएस में ठीक से काम करता है।
user253751

@ मिनीबिस: एचएम, अच्छा सवाल। इसके लिए पार्सिंग नियम क्या होंगे invariant? या तो वे उसी तरह के होते हैं en_us, जिस स्थिति में, क्यों परेशान होते हैं, या वे किसी अन्य देश से मेल खाते हैं, किस मामले में, किसके बजाय यह एक और क्यों en_us, या उनके विशिष्ट नियम हैं जो किसी भी देश से मेल नहीं खाते हैं , जो बेकार होगा। वास्तव में कोई "सही जवाब" नहीं है : 12,345.67और 12 345,67कोई भी "डिफ़ॉल्ट नियम" कुछ देशों के लिए काम करेगा, और दूसरों के लिए काम नहीं करेगा।
आर्सेनी मूरज़ेंको

3
@ArseniMourzenko यह आम तौर पर एक "सबसे कम आम भाजक" है और सिंटैक्स के समान कई प्रोग्रामिंग भाषाओं का उपयोग होता है (जो संस्कृति-अपरिवर्तनीय भी है)। 1234512345 के रूप में पार्स करता है, 12 345या 12,345या 12.345कोई त्रुटि है। 12.345उपयोग करने की प्रोग्रामिंग भाषा सम्मेलन के अनुसार, एक अपरिवर्तनीय फ्लोटिंग-पॉइंट संख्या के रूप में हमेशा पैदावार 12.345 होती है। दशमलव विभाजक के रूप में। स्ट्रिंग्स को उनके यूनिकोड कोड बिंदुओं और केस-संवेदी द्वारा हल किया जाता है। और इसी तरह।
user253751

11

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

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

कोड को पढ़ना और तर्क देना जितना सरल है, उसे बनाए रखना और बग को स्पॉट करना उतना ही सरल है, इसलिए यह आपके और आपके नियोक्ता के लिए समय और पैसा बचाता है।


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

यह एक अच्छी बात है। मेरे पास कोड को पढ़ने / तर्क करने के लिए सरल कोड के साथ एक समस्या है, क्योंकि पढ़ने के लिए सरल या कारण कोड का कुछ अस्पष्ट और व्यक्तिपरक विशेषता है।
इल रोथ

एक बार जब आप परिवर्तनशील चर में जोड़ना शुरू करते हैं, जिनमें से कुछ में एकल फ़ंक्शन से परे स्कोप होता है, लेकिन वेरिएबल स्कोप फ़ंक्शन के लिए स्थानीय होने पर भी असाइनमेंट ऑपरेशन को हतोत्साहित क्यों किया जाता है?
राहुलगा_देव २ '

9

लोग "आसान कारण के बारे में" शब्द के चारों ओर फेंकते हैं, लेकिन कभी भी इसका मतलब नहीं बताते हैं। निम्नलिखित उदाहरण पर विचार करें:

result1 = foo("bar", 12)
// 100 lines of code
result2 = foo("bar", 12)

कर रहे हैं result1और result2उसी या अन्य? प्रासंगिक पारदर्शिता के बिना, आपके पास कोई विचार नहीं है। आपको वास्तव में fooयह सुनिश्चित करने के लिए शरीर को पढ़ना होगा , और संभवतः किसी भी फ़ंक्शन के शरीर को fooकॉल करता है, और आगे।

लोग इस बोझ को नोटिस नहीं करते हैं क्योंकि वे इसके आदी हैं, लेकिन अगर आप एक या दो महीने के लिए पूरी तरह से कार्यात्मक वातावरण में काम करते हैं तो वापस आ जाओ तो आपको यह महसूस होगा, और यह एक बहुत बड़ी बात है

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


1
आपने उल्लेख किया कि संदर्भात्मक पारदर्शिता आपको फू () को कॉल के परिणाम के बारे में तर्क करने और यह जानने की अनुमति देती है कि क्या समान हैं result1और क्या result2हैं। एक और महत्वपूर्ण पहलू यह है कि यदि foo("bar", 12)संदर्भात्मक रूप से पारदर्शी है, तो आपको खुद से यह पूछने की ज़रूरत नहीं है कि क्या इस कॉल ने कहीं और कुछ प्रभाव उत्पन्न किए हैं (कुछ चर सेट करें? एक फ़ाइल हटा दी गई है? जो भी हो)।
जियोर्जियो

केवल "संदर्भात्मक अखंडता" से मैं परिचित हूं, जिसमें रिलेशनल डेटाबेस शामिल हैं।
मार्क

1
@ मार्क यह एक टाइपो है। कार्ल का तात्पर्य संदर्भात्मक पारदर्शिता से था, जैसा कि उनके उत्तर के बाकी हिस्सों से स्पष्ट है।
एंड्रेस एफ।

6

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

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

वे बड़े कार्य जादू करते हैं और मुझे उन्हें छूने से डर लगता है क्योंकि वे शानदार तरीके से टूट सकते हैं।

इतना शुद्ध कार्य केवल कार्यात्मक प्रोग्रामिंग के लिए नहीं, बल्कि हर कार्यक्रम के लिए कुछ है।

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