क्या हमें ओवरलोडेड तरीकों का नाम बदलना चाहिए?


14

इन विधियों से युक्त एक अंतरफलक मान लें:

Car find(long id);

List<Car> find(String model);

क्या इस तरह उनका नाम बदलना बेहतर है?

Car findById(long id);

List findByModel(String model);

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

इसलिए मेरा प्रश्न अधिक सामान्य है: कोड में अतिभारित तरीकों का उपयोग करने से क्या फायदा है क्योंकि यह पठनीयता को कम करता है?


4
जब तक आप सुसंगत हैं तब तक या तो विधि स्वीकार्य है।
ChrisF

ओवरलोडिंग और एक विधि को ओवरराइड करने के बीच एक संबंध है। हालाँकि यह लेख आपके सुझाव का समर्थन करता है - यह रुचि का हो सकता है: roseindia.net/javatutorials/…
NoChance

जवाबों:


23

यह कई अन्य खराब पठनीयता प्रथाओं की तुलना में एक अपेक्षाकृत मामूली समस्या है जिसे आप अतिसंवेदनशील हो सकते हैं, इसलिए मैं कहूंगा कि यह ज्यादातर स्वाद का मामला है कि आप अपने तरीकों का नाम कैसे देते हैं।

इसके साथ ही, यदि आप इसके बारे में कुछ करने जा रहे हैं, तो मैं इस अभ्यास का पालन करूंगा:

  • अधिभार यदि ...

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

  • एक अलग नाम का उपयोग करें यदि ...

    विधियां अलग-अलग चीजें करती हैं या विभिन्न आउटपुट (जैसे आपका मामला) वापस करती हैं। यदि आप डेटाबेस तक पहुँचते हैं और एक नहीं करता है तो आप एक अलग नाम का उपयोग करने पर विचार कर सकते हैं।

    इसके अलावा, अगर लौटा हुआ प्रकार अलग है, तो मैं यह संकेत देने के लिए क्रिया को भी बदलूंगा:

    Car findById(long id);
    
    List findAllByModel(String model);
    

3
एफडब्ल्यूआईडब्ल्यू, मैं कहूंगा कि थोड़ा अधिक दृढ़ता से: "विधियां बिल्कुल उसी अनुबंध का पालन ​​करती हैं ..." यानी तर्क प्रकार / गिनती कोई फर्क नहीं पड़ता - फ़ंक्शन कॉल के शब्दार्थ समान हैं। यदि तर्क प्रकार / मायने रखता है, तो आपको अधिभार नहीं देना चाहिए।
mcmcc

4

मैं हर मामले में एक अलग नाम का उपयोग करने की सलाह दूंगा। यह संभव है कि भविष्य में किसी समय, आप List<Car> findByMake(String make)इसके विपरीत एक और विधि जोड़ना चाहें List<Car> findByModel(String model)। तो अचानक, सब कुछ कॉल findकरना समझ में आना बंद हो जाता है। आपके तरीकों से अनजाने में गलत तरीके से उपयोग किए जाने की संभावना कम होती है, यदि उनके नाम अधिक जानकारी देते हैं कि उनका उपयोग कैसे किया जाना चाहिए।


1
निष्पक्ष होने के लिए, यह उतना मुद्दा नहीं होगा, अगर कार्यक्षमता को वस्तुओं द्वारा अधिक स्पष्ट रूप से दर्शाया गया है: find(Make val)और find(Model val)। फिर, सुविधा के तरीके जैसे कि findByMake(String val)बहुत अधिक स्पष्ट होंगे कि वे वास्तव में क्या कर रहे हैं। आखिरकार, Stringयह या तो एक मेक या मॉडल नहीं है, इसलिए विधि को यह समझाने के लिए चाहिए कि यह वास्तव में क्या कर रहा है।
निकोल

4

यदि आप किसी विधि का नाम बदलते हैं, तो यह अब अतिभारित होने वाला नहीं है। अपने आप में, ओवरलोडिंग जरूरी कोड को कम पठनीय नहीं बनाता है, हालांकि यह सिंटैक्स स्पष्ट नहीं होने पर कार्यान्वयन को और अधिक कठिन बना सकता है।

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

तो यह कर:

void MyMethod(int param1, int param2 = 10)
{
    ...
}

आपको ऐसा करने से बचाता है:

void MyMethod(int param1)
{
    MyMethod(param1, Param2Default);
}

void MyMethod(int param1, int param2)
{
    ....
}

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

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

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

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


0

जब तक विधियाँ एक ही चीज़ को वापस नहीं करतीं और एक ही अनुबंध का पालन करती हैं, तब तक ओवरलोडिंग के अनुकूल रहें। ओवरलोडिंग कॉलिंग कोड को अनावश्यक रूप से पैरामीटर प्रकार से मुक्त करता है।

मान लीजिए कि कॉलिंग फ़ंक्शन पैरामीटर के रूप में एक खोज क्वेरी प्राप्त करता है और कॉल करने से पहले और / या बाद में कुछ अन्य प्रसंस्करण करता है find

void tryToSellCars(String which) {
    /* grab an airhorn, inflatable tube guy... */
    List<Car> cars = find(which);
    /* expound virtues of each car in detail... */
}

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

void tryToSellCar(CarQuery which) {
    /* grab airhorn, inflate tube guy... */
    List<Car> cars = find(which)
    /* expound virtues of each car in detail... */
}

यदि आप लागू करते हैं findByIdऔर findByQueryObjectअलग-अलग करते हैं, तो आपको उस परिवर्तन को करने के लिए हर कॉल का शिकार करना होगा। उदाहरण में, मैंने केवल एक शब्द को बदल दिया और मुझे किया गया।


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