वैकल्पिक पैरामीटर या अतिभारित कंस्ट्रक्टर


28

मैं एक कार्यान्वित कर रहा हूं DelegateCommand, और जब मैं कंस्ट्रक्टर को लागू करने वाला था, तो मैं निम्नलिखित दो डिज़ाइन विकल्पों के साथ आया था:

1: कई अतिभारित कंस्ट्रक्टर वाले

public DelegateCommand(Action<T> execute) : this(execute, null) { }

public DelegateCommand(Action<T> execute, Func<T, bool> canExecute)
{
    this.execute = execute;
    this.canExecute = canExecute;
}

2: वैकल्पिक पैरामीटर के साथ केवल एक कंस्ट्रक्टर होना

public DelegateCommand(Action<T> execute, Func<T, bool> canExecute = null)
{
    this.execute = execute;
    this.canExecute = canExecute;
}

मुझे नहीं पता कि मुझे कौन सा उपयोग करना है क्योंकि मुझे नहीं पता कि दोनों प्रस्तावित तरीकों में से किसी के भी संभावित फायदे / नुकसान हैं। दोनों को इस तरह कहा जा सकता है:

var command = new DelegateCommand(this.myExecute);
var command2 = new DelegateCommand(this.myExecute, this.myCanExecute);

क्या कोई कृपया मुझे सही दिशा में संकेत दे सकता है और प्रतिक्रिया दे सकता है?


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

1
स्टैटिक कंस्ट्रक्टर (जैसे Bitmap.FromFile) भी एक विकल्प हैं
ब्लूराजा - डैनी पीफ्लुगुएफ्ट


2
@Laiv क्या मुझे कुछ याद आ रहा है? वे एक ही तरीके से उपयोग किए जाते हैं और इस प्रकार एक ही हस्ताक्षर होते हैं। आप संदर्भ नहीं खोज सकते हैं और बता सकते हैं कि कॉलर किस बारे में सोच रहा था। ऐसा लगता है कि आप ओपी के पास उस दूसरे तर्क का भी उल्लेख करना चाहिए या नहीं, लेकिन ओपी के बारे में ऐसा नहीं है (और वे अच्छी तरह जानते हैं कि उन्हें कभी-कभी दोनों की आवश्यकता होती है, इसलिए वे पूछ रहे हैं)।
कैट

2
@ ओपन के लिए संकलक | प्रगति 10.2B उन्हें अनदेखा करता है। बहुत ज्यादा हमारी गैर-ब्रेकिंग पद्धति परिवर्तन रणनीति को मार डाला; इसके बजाय, हमें उसी प्रभाव के लिए ओवरलोडिंग का उपयोग करने की आवश्यकता थी।
ब्रेट

जवाबों:


24

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

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

आपके उदाहरणों में, हालांकि उनके बीच कोई अंतर नहीं है क्योंकि यहां तक ​​कि माध्यमिक निर्माता nullडिफ़ॉल्ट मान के रूप में गुजरता है और प्राथमिक निर्माता को डिफ़ॉल्ट मूल्य भी पता होना चाहिए। मुझे लगता है कि यह नहीं करना चाहिए।

इसका मतलब है कि अगर इसे इस तरह से लागू किया जाता है तो यह क्लीनर और बेहतर रूप से अलग हो जाएगा:

public DelegateCommand(Action<T> execute) : this(execute, _ => true) { }

public DelegateCommand(Action<T> execute, Func<T, bool> canExecute)
{
    this.execute = execute ?? throw new ArgumentNullException(..);
    this.canExecute = canExecute ?? throw new ArgumentNullException(..);
}

नोटिस _ => trueप्राथमिक निर्माता है कि है अब भी के लिए सभी मापदंडों की जाँच करने के लिए पारित कर दिया nullहै और किसी भी चूक के बारे में परवाह नहीं है।


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


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


12
दूसरी ओर बहुत सारे मापदंडों को वैकल्पिक बनाना भ्रामक होगा ... ईमानदार होने के लिए, बहुत अधिक पैरामीटर होने (भले ही वे वैकल्पिक हों या नहीं) भ्रमित हो रहे हैं।
एंडी

1
@ डेविडपैकर मैं आपसे सहमत हूं, लेकिन कितने पैरामीटर बहुत अधिक हैं एक और कहानी है, मुझे लगता है; ;-)
t3chb0t

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

1
उदाहरण के लिए, मान लीजिए कि मेरे पास एक वर्ग है जो स्ट्रिंग को प्रारूपित करता है, जिसे मैं वैकल्पिक रूप से किसी CultureInfoऑब्जेक्ट के साथ बना सकता हूं । मैं एक एपीआई पसंद करूंगा जिसने CultureInfoपैरामीटर को एक अतिरिक्त पैरामीटर के माध्यम से आपूर्ति करने की अनुमति दी , लेकिन जोर दिया कि अगर यह आपूर्ति की गई थी तो यह नहीं होना चाहिए null। इस तरह से आकस्मिक nullमूल्यों का अर्थ "कोई नहीं" के रूप में गलत व्याख्या नहीं है।
गैरी मैकगिल

मुझे यकीन नहीं है कि एक्स्टेंसिबिलिटी वास्तव में वैकल्पिक मापदंडों के खिलाफ एक कारण है ; यदि आपके पास आवश्यक पैरामीटर हैं और कभी भी उनकी संख्या बदल दें तो आपको एक नया निर्माणकर्ता और Obsoleteपुराना बनाना होगा यदि आप चीजों को तोड़ने से बचना चाहते हैं, चाहे आपके पास वैकल्पिक पैरामीटर हो या नहीं। वैकल्पिक मापदंडों के साथ आपको केवल एक को Obsoleteहटाना होगा।
हेरोहार्ट

17

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

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


3

मुझे लगता है कि दो अलग-अलग मामले हैं जिनके लिए प्रत्येक दृष्टिकोण चमक सकता है।

सबसे पहले, जब हमारे पास सरल निर्माता होते हैं (जो आमतौर पर मेरे अनुभव में होता है), मैं चमकने के लिए वैकल्पिक तर्कों पर विचार करूंगा।

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

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


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