नामित पैरामीटर्स कोड को आसान बनाने के लिए पढ़ें, कठिन लिखने के लिए
जब मैं कोड का एक टुकड़ा पढ़ रहा होता हूं, तो नामित पैरामीटर संदर्भ प्रस्तुत कर सकता है जो कोड को समझने में आसान बनाता है। उदाहरण के लिए इस निर्माता पर विचार करें Color(1, 102, 205, 170)
:। पृथ्वी पर उसका क्या अर्थ है? वास्तव में, Color(alpha: 1, red: 102, green: 205, blue: 170)
यह पढ़ना बहुत आसान होगा। लेकिन अफसोस, कंपाइलर "नहीं" कहता है - यह चाहता है Color(a: 1, r: 102, g: 205, b: 170)
। नामित मापदंडों का उपयोग करके कोड लिखते समय, आप सटीक नामों को देखने के लिए अनावश्यक समय बिताते हैं - कुछ मापदंडों के सटीक नामों को भूलना आसान होता है, जितना कि उनके आदेश को भूलना।
DateTime
लगभग एक जैसे इंटरफेस वाले पॉइंट्स और ड्यूरेशन के लिए दो सिबलिंग क्लास वाले एपीआई का इस्तेमाल करते समय यह मुझे एक बार हो जाता है। जबकि अन्य इकाइयों के लिए DateTime->new(...)
एक second => 30
तर्क, DateTime::Duration->new(...)
वांछित seconds => 30
, और समान स्वीकार किया गया । हां, यह पूरी तरह से समझ में आता है, लेकिन इससे मुझे पता चला कि नामित पैरामीटर use उपयोग में आसानी।
बुरे नाम भी पढ़ने में आसान नहीं बनाते हैं
एक और उदाहरण है कि कैसे नामित पैरामीटर खराब हो सकते हैं शायद आर भाषा है। कोड का यह टुकड़ा एक डेटा प्लॉट बनाता है:
plot(plotdata$n, plotdata$mu, type="p", pch=17, lty=1, bty="n", ann=FALSE, axes=FALSE)
आप x और y डेटा पंक्तियों के लिए दो स्थितियुक्त तर्क देखते हैं , और फिर नामांकित मापदंडों की सूची। डिफॉल्ट के साथ कई और विकल्प हैं, और केवल वे ही सूचीबद्ध हैं जिनके डिफॉल्ट्स मैं बदलना या स्पष्ट रूप से निर्दिष्ट करना चाहता था। एक बार जब हम अनदेखा कर देते हैं कि यह कोड जादुई संख्याओं का उपयोग करता है, और एनमों का उपयोग करके लाभान्वित हो सकता है (यदि आर के पास कोई भी है!), तो मुद्दा यह है कि इनमें से कई पैरामीटर नाम अनिर्णायक हैं।
pch
वास्तव में प्लॉट चरित्र है, ग्लिफ़ जिसे हर डेटा बिंदु के लिए तैयार किया जाएगा। 17
एक खाली चक्र है, या ऐसा ही कुछ।
lty
लाइन प्रकार है। यहाँ 1
एक ठोस रेखा है।
bty
बॉक्स प्रकार है। "n"
भूखंड के चारों ओर खींचे जा रहे एक बॉक्स से बचने के लिए इसे स्थापित करना ।
ann
अक्ष एनोटेशन की उपस्थिति को नियंत्रित करता है।
किसी ऐसे व्यक्ति के लिए जो यह नहीं जानता कि प्रत्येक संक्षिप्त नाम का क्या अर्थ है, ये विकल्प बल्कि भ्रमित करने वाले हैं। इससे यह भी पता चलता है कि R इन लेबलों का उपयोग क्यों करता है: स्व-दस्तावेजीकरण कोड के रूप में नहीं, बल्कि (डायनेमिक रूप से टाइप की गई भाषा के रूप में) मानों को उनके सही चर में मैप करने के लिए।
पैरामीटर और हस्ताक्षर के गुण
समारोह हस्ताक्षरों में निम्नलिखित गुण हो सकते हैं:
- तर्क का आदेश दिया जा सकता है या अनियंत्रित किया जा सकता है,
- नाम या अनाम,
- आवश्यक या वैकल्पिक।
- हस्ताक्षर भी आकार या प्रकार से अतिभारित हो सकते हैं,
- और varargs के साथ एक अनिर्दिष्ट आकार हो सकता है।
विभिन्न भाषाएं इस प्रणाली के विभिन्न निर्देशांक पर उतरती हैं। सी में, तर्कों का आदेश दिया जाता है, अनाम, हमेशा आवश्यक, और वैरग हो सकते हैं। जावा में स्थिति समान है, सिवाय इसके कि हस्ताक्षर अतिभारित हो सकते हैं। ऑब्जेक्टिव सी में, सिग्नेचर का आदेश दिया जाता है, नाम दिया जाता है, आवश्यकता होती है, और इसे ओवरलोड नहीं किया जा सकता है क्योंकि यह सी के चारों ओर सिंटैक्टिक चीनी है।
वैरिकाज़ के साथ डायनामिक रूप से टाइप की गई भाषाएं (कमांड लाइन इंटरफेस, पर्ल,…) वैकल्पिक नामित मापदंडों का अनुकरण कर सकती हैं। सिग्नेचर साइज़ ओवरलोडिंग वाली भाषाओं में स्थितीय वैकल्पिक मापदंडों जैसा कुछ होता है।
नामांकित पैरामीटर को लागू करने के लिए कैसे नहीं
नामित मापदंडों के बारे में सोचते समय, हम आमतौर पर नामित, वैकल्पिक, अनियंत्रित पैरामीटर मान लेते हैं। इन्हें लागू करना मुश्किल है।
वैकल्पिक पैरामीटर में डिफ़ॉल्ट मान हो सकते हैं। इन्हें तथाकथित फ़ंक्शन द्वारा निर्दिष्ट किया जाना चाहिए और कॉलिंग कोड में संकलित नहीं किया जाना चाहिए। अन्यथा, सभी निर्भर कोड recompiling किए बिना चूक को अद्यतन नहीं किया जा सकता है।
अब एक महत्वपूर्ण सवाल यह है कि तर्कों को वास्तव में फ़ंक्शन में कैसे पारित किया जाता है। आदेश दिए गए मापदंडों के साथ, आर्ग्स को एक रजिस्टर में, या स्टैक पर उनके अंतर्निहित क्रम में पारित किया जा सकता है। जब हम एक पल के लिए रजिस्टरों को बाहर करते हैं, तो समस्या यह है कि स्टैक पर अनियोजित वैकल्पिक तर्क कैसे रखे जाएं।
उसके लिए, हमें वैकल्पिक तर्कों पर कुछ आदेश की आवश्यकता है। क्या होगा अगर घोषणा कोड बदल दिया जाए? जैसा कि आदेश अप्रासंगिक है, फ़ंक्शन घोषणा में एक पुनरावृत्ति स्टैक पर मूल्यों की स्थिति को नहीं बदलना चाहिए। हमें यह भी विचार करना चाहिए कि क्या नया वैकल्पिक पैरामीटर जोड़ना संभव है। उपयोगकर्ताओं के दृष्टिकोण से ऐसा लगता है, क्योंकि कोड जो पहले उस पैरामीटर का उपयोग नहीं करता था, उसे अभी भी नए पैरामीटर के साथ काम करना चाहिए। तो यह आदेश को घोषणा में उपयोग करने या वर्णमाला के क्रम का उपयोग करने जैसे आदेशों को बाहर करता है।
उप-संकलन और लिस्कोव प्रतिस्थापन सिद्धांत के प्रकाश में भी इस पर विचार करें - संकलित आउटपुट में, एक ही निर्देश संभवतया नए नामित मापदंडों के साथ एक उपप्रकार पर विधि को लागू करने में सक्षम होना चाहिए, और एक सुपरटेप पर।
संभव कार्यान्वयन
यदि हमारे पास एक निश्चित क्रम नहीं हो सकता है, तो हमें कुछ अनियंत्रित डेटा संरचना की आवश्यकता है।
सबसे सरल कार्यान्वयन केवल मानों के साथ मापदंडों का नाम पारित करना है। इस प्रकार पेरल्स में या कमांड लाइन टूल्स के साथ पैराम्स का नामकरण किया जाता है। यह ऊपर वर्णित सभी एक्सटेंशन समस्याओं को हल करता है, लेकिन अंतरिक्ष का एक बड़ा अपशिष्ट हो सकता है - प्रदर्शन-महत्वपूर्ण कोड में विकल्प नहीं। इसके अलावा, इन नामित पारमों को संसाधित करना एक स्टैक से बस मूल्यों को पॉप करने की तुलना में बहुत अधिक जटिल है।
दरअसल, स्ट्रिंग पूलिंग का उपयोग करके अंतरिक्ष आवश्यकताओं को कम किया जा सकता है, जो बाद की स्ट्रिंग तुलनाओं को सूचक तुलनाओं को कम कर सकता है (सिवाय इसके कि जब यह गारंटी नहीं दी जा सकती है कि स्थिर तार वास्तव में पूल किए जाते हैं, तो उस स्थिति में दोनों तारों की तुलना की जाएगी। विस्तार)।
इसके बजाय, हम एक चतुर डेटा संरचना भी पारित कर सकते हैं जो नामित तर्कों के शब्दकोश के रूप में काम करती है। यह कॉलर की तरफ सस्ता है, क्योंकि कुंजी का सेट कॉल लोकेशन पर स्टेटिक रूप से जाना जाता है। यह एक सही हैश फ़ंक्शन बनाने या एक ट्राइक को पहले से तैयार करने की अनुमति देगा। कैली को अभी भी सभी संभावित पैरामीटर नामों के अस्तित्व के लिए परीक्षण करना होगा जो कुछ महंगे हैं। ऐसा ही कुछ पाइथन द्वारा उपयोग किया जाता है।
तो यह ज्यादातर मामलों में बहुत महंगा है
यदि नामांकित मापदंडों के साथ एक फ़ंक्शन ठीक से एक्स्टेंसिबल होना है, तो एक निश्चित आदेश नहीं माना जा सकता है। तो केवल दो समाधान हैं:
- नामित परमिशन के आदेश को हस्ताक्षर का हिस्सा बनाएं, और बाद के परिवर्तनों को अस्वीकार करें। यह स्व-दस्तावेजीकरण कोड के लिए उपयोगी है, लेकिन वैकल्पिक तर्कों के साथ मदद नहीं करता है।
- केली के लिए एक कुंजी-मूल्य डेटा संरचना पास करें, जिसके बाद उपयोगी जानकारी निकालना होगा। यह तुलना में बहुत महंगा है, और आमतौर पर केवल प्रदर्शन पर जोर दिए बिना स्क्रिप्टिंग भाषाओं में देखा जाता है।
अन्य नुकसान
एक फ़ंक्शन घोषणा में चर नाम आमतौर पर कुछ आंतरिक अर्थ होते हैं और इंटरफ़ेस का हिस्सा नहीं होते हैं - भले ही कई प्रलेखन उपकरण अभी भी उन्हें दिखाएंगे। कई मामलों में आप आंतरिक चर और संबंधित नाम तर्क के लिए अलग-अलग नाम चाहते हैं। नामांकित पैरामीटर के बाहरी रूप से दिखाई देने वाले नामों को चुनने की अनुमति नहीं देने वाली भाषाएं उनमें से बहुत कुछ हासिल नहीं करती हैं यदि चर नाम को ध्यान में रखते हुए उपयोग नहीं किया जाता है।
नामित तर्कों के अनुकरण के साथ एक मुद्दा कॉलर की ओर स्थिर जाँच की कमी है। तर्कों का एक शब्दकोश (आप, पायथन को देखते हुए) गुजरते समय यह भूलना आसान है। यह महत्वपूर्ण है क्योंकि एक शब्दकोश को पारित करना एक सामान्य समाधान है, उदाहरण के लिए जावास्क्रिप्ट में foo({bar: "baz", qux: 42})
:। यहां, न तो मूल्यों के प्रकार और न ही कुछ नामों के अस्तित्व या अनुपस्थिति को सांख्यिकीय रूप से जांचा जा सकता है।
नामांकित पैरामीटर का अनुकरण करना (सांख्यिकीय रूप से टाइप की गई भाषाओं में)
बस स्ट्रिंग्स को कुंजियों के रूप में उपयोग करना, और एक मूल्य के रूप में किसी भी वस्तु को स्थिर प्रकार की चेकर की उपस्थिति में बहुत उपयोगी नहीं है। हालांकि, नामित तर्कों को संरचना, या वस्तु शाब्दिक के साथ अनुकरण किया जा सकता है:
// Java
static abstract class Arguments {
public String bar = "default";
public int qux = 0;
}
void foo(Arguments args) {
...
}
/* using an initializer block */
foo(new Arguments(){{ bar = "baz"; qux = 42; }});