एक विधि तर्क को एक अच्छा अभ्यास नाम देने के लिए एक चर को परिभाषित करना है?


73

पठनीयता के लिए मैं अक्सर स्वयं को अस्थायी चर को परिभाषित करते हुए पाता हूं, जैसे कि निम्नलिखित कोड

var preventUndo = true;
doSomething(preventUndo);

इसका छोटा संस्करण यह होगा,

doSomething(true);

लेकिन जब मैं कोड पर वापस आता हूं तो मुझे अक्सर आश्चर्य होता है कि इसका क्या trueमतलब है। क्या इस तरह के कॉंडम के लिए एक सम्मेलन है?


5
क्या आप किसी प्रकार की आईडीई का उपयोग करते हैं? अधिकांश के पास यह संकेत करने का कोई तरीका होगा कि आप जिस फ़ंक्शन को कॉल कर रहे हैं उसके पैरामीटर क्या हैं जो कुछ ऐसा करने की आवश्यकता को कम करता है।
मैथ्यू शारले

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

11
यदि भाषा इसका समर्थन करती है, तो आप एक गणना का उपयोग कर सकते हैं जैसेdoSomething( Undo.PREVENT )
जेम्स पी।

4
लेकिन आप परिभाषित कर सकते हैं Undo = { PREVENT = true, DONT_PREVENT = false }। लेकिन जावास्क्रिप्ट में, कन्वेंशन को इस तरह करना है: function myFunction( mandatoryArg1, mandatoryArg2, otherArgs ) { /*...*/ }और फिर myFunction( 1, 2, { option1: true, option2: false } )
xavierm02

6
यह निश्चित रूप से भाषा पर निर्भर करता है। यदि यह अजगर थे, उदाहरण के लिए, मैं सिर्फ कीवर्ड तर्क का उपयोग करने का सुझाव doSomething(preventUndo=True)
दूंगा

जवाबों:


117

वैरिएबल की व्याख्या करना

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

अच्छी गुणवत्ता कोड पाठक के लिए इरादे का संचार करता है; और एक पेशेवर डेवलपर के रूप में पठनीयता और स्थिरता आपके # 1 लक्ष्य हैं।

जैसे, अंगूठे का नियम मैं सुझाऊंगा: यदि आपके पैरामीटर्स का उद्देश्य तुरंत स्पष्ट नहीं है, तो एक अच्छा नाम देने के लिए एक चर का उपयोग करने के लिए स्वतंत्र महसूस करें। मुझे लगता है कि यह सामान्य रूप से एक अच्छा अभ्यास है (जब तक कि दुरुपयोग न हो)। यहाँ एक त्वरित, आकस्मिक उदाहरण दिया गया है - विचार करें:

editButton.Enabled = (_grid.SelectedRow != null && ((Person)_grid.SelectedRow).Status == PersonStatus.Active);

बनाम थोड़ा लंबा, लेकिन यकीनन स्पष्ट:

bool personIsSelected = (_grid.SelectedRow != null);
bool selectedPersonIsEditable = (personIsSelected && ((Person)_grid.SelectedRow).Status == PersonStatus.Active)
editButton.Enabled = (personIsSelected && selectedPersonIsEditable);

बूलियन पैरामीटर

आपका उदाहरण वास्तव में हाइलाइट करता है कि एपीआई में बुलियन अक्सर एक बुरा विचार क्यों होते हैं - कॉलिंग पक्ष पर, वे यह समझाने के लिए कुछ नहीं करते हैं कि क्या हो रहा है। विचार करें:

ParseFolder(true, false);

आपको यह देखना होगा कि उन मापदंडों का क्या मतलब है; अगर वे एनम थे, तो यह बहुत अधिक स्पष्ट होगा:

ParseFolder(ParseBehaviour.Recursive, CompatibilityOption.Strict);

संपादित करें:

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


28
जब तक आप नामित पैरामीटर (.NET फ्रेमवर्क में तर्कों का नाम) का उपयोग नहीं करते हैं, तब तक मामला doSomething(preventUndo: true);काफी स्पष्ट है। इसके अलावा, अपने एपीआई में हर बूलियन के लिए एक पहेली बना? गंभीरता से?
आर्सेनी मूरज़ेंको

12
@ मेनमा: यदि आप जिस भाषा का उपयोग कर रहे हैं, वह नामांकित तर्क का समर्थन करने के लिए पर्याप्त शांत नहीं है, तो एनम का उपयोग करना एक अच्छा विकल्प है। इसका मतलब यह नहीं है कि आपको हर जगह व्यवस्थित रूप से परिचय देना चाहिए।
जियोर्जियो

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

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

3
यही कारण है कि एमएस उन सभी नए सामानों का अच्छा सारांश जारी करता है जो उन्होंने प्रत्येक संस्करण में जोड़े हैं, मुझे नहीं लगता कि यह हर दो साल में पढ़ने के लिए बहुत काम करता है: msdn.microsoft.com/en- us / Library / bb383815% 28v = vs.100% 29.aspx
नैट CK

43

आप की जरूरत नहीं है कोड न लिखें।

यदि आपको doSomething(true)समझना मुश्किल है, तो आपको या तो एक टिप्पणी जोड़नी चाहिए:

// Do something and prevent the undo.
doSomething(true);

या, यदि भाषा इसका समर्थन करती है, तो पैरामीटर नाम जोड़ें:

doSomething(preventUndo: true);

अन्यथा, आपको अपनी आईडीई पर भरोसा करना चाहिए ताकि आपको फोन किया जा सके।

यहाँ छवि विवरण दर्ज करें

मामले जहां यह उपयोगी है

एक अतिरिक्त चर डालना उपयोगी हो सकता है:

  1. डिबगिंग उद्देश्यों के लिए:

    var productId = this.Data.GetLastProductId();
    this.Data.AddToCart(productId);
    

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

  2. यदि आपके पास बहुत सारे मापदंडों के साथ एक विधि है और प्रत्येक पैरामीटर एक मूल्यांकन से जाता है। एक पंक्ति में, यह पूरी तरह से अपठनीय हो सकता है।

    // Even with indentation, this is unreadable.
    var doSomething(
        isSomethingElse ? 0 : this.getAValue(),
        this.getAnotherOne() ?? this.default,
        (a + b + c + d + e) * f,
        this.hello ? this.world : (this.hello2 ? this.world2 : -1));
    
  3. यदि किसी पैरामीटर का मूल्यांकन बहुत जटिल है। एक कोड का उदाहरण मैंने देखा है:

    // Wouldn't it be easier to have several if/else's (maybe even in a separate method)?
    do(something ? (hello ? world : -1) : (programmers ? stackexchange : (com ? -1 : 0)));
    

अन्य मामलों में क्यों नहीं?

आपको साधारण मामलों में अतिरिक्त चर क्यों नहीं बनाने चाहिए?

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

  2. लेकिन नाम को अलग-अलग करने के जोखिम के कारण आप चर को पैरामीटर के नाम पर देते हैं।

    उदाहरण:

    मान लीजिए कि मूल कोड है:

    void doSomething(bool preventUndo)
    {
        // Does something very interesting.
        undoHistory.removeLast();
    }
    
    // Later in code:
    var preventUndo = true;
    doSomething(preventUndo);
    

    बाद में, एक डेवलपर doSomethingजो नोटिस पर काम कर रहा है , हाल ही में, पूर्ववत इतिहास ने दो नए तरीके पेश किए:

    undoHistory.clearAll() { ... }
    undoHistory.disable() { ... }
    

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

    doSomething(bool hideLastUndo) { ... }
    doSomething(bool removeAllUndo) { ... }
    doSomething(bool disableUndoFeature) { ... }
    

    तो अब आपके पास है:

    void doSomething(bool hideLastUndo)
    {
        // Does something very interesting.
        undoHistory.removeLast();
    }
    
    // Later in code, very error prone, while the signature of the method is clear:
    var preventUndo = true;
    doSomething(preventUndo);
    

एनम के बारे में क्या?

कुछ अन्य लोगों ने एनमों का उपयोग करने का सुझाव दिया। जबकि यह तत्काल समस्या को हल करता है, यह एक बड़ा बनाता है। चलो एक नज़र डालते हैं:

enum undoPrevention
{
    keepInHistory,
    prevent,
}

void doSomething(undoPrevention preventUndo)
{
    doTheJob();
    if (preventUndo == undoPrevention.prevent)
    {
        this.undoHistory.discardLastEntry();
    }
}

doSomething(undoPrevention.prevent);

उस के साथ समस्याएं:

  1. यह बहुत अधिक कोड है। if (preventUndo == undoPrevention.prevent)? गंभीरता से ?! मैं ifहर बार ऐसा लिखना नहीं चाहता ।

  2. Enum में एक तत्व जोड़ना बाद में बहुत लुभावना है, अगर मैं उसी Enum का उपयोग कहीं और कर रहा हूँ। अगर मैं इसे इस तरह से संशोधित करूं तो क्या होगा:

    enum undoPrevention
    {
        keepInHistory,
        prevent,
        keepButDisable, // Keeps the entry in the history, but makes it disabled.
    }
    

    अब क्या होगा? क्या doSomethingविधि उम्मीद के मुताबिक काम करेगी ? इसे रोकने के लिए, शुरुआत से ही इस तरीके को लिखना होगा:

    void doSomething(undoPrevention preventUndo)
    {
        if (![undoPrevention.keepInHistory, undoPrevention.prevent].contains(preventUndo))
        {
            throw new ArgumentException('preventUndo');
        }
    
        doTheJob();
        if (preventUndo == undoPrevention.prevent)
        {
            this.undoHistory.discardLastEntry();
        }
    }
    

    जिस संस्करण में बूलियन का उपयोग होता है वह बहुत अच्छा लगने लगता है!

    void doSomething(bool preventUndo)
    {
        doTheJob();
        if (preventUndo)
        {
            this.undoHistory.discardLastEntry();
        }
    }
    

3
"यह बहुत अधिक कोड है। यदि (रोका गया == undoPrevention.prevent)? गंभीरता से? मैं हर बार ऐसे आईएफएस नहीं लिखना चाहता।": एक अच्छे पुराने स्विच स्टेटमेंट का उपयोग करने के बारे में क्या? इसके अलावा, यदि आप एक बूलियन का उपयोग करते हैं, तो आपको वैसे भी एक बयान की आवश्यकता है। ईमानदारी से, इस बिंदु पर आपकी आलोचना मुझे थोड़ी कृत्रिम लगती है।
जियोर्जियो

1
मुझे यहां एक वैकल्पिक समाधान याद आ रहा है। क्या आप कह रहे हैं कि उसे कुछ भी नहीं कहना चाहिए, यह सच है और गलत है और IDE (जो वह उपयोग नहीं करता है) पर भरोसा करता है? एक टिप्पणी चर नाम की तरह सड़ सकती है।
सुरक्षित करें

2
@ सुपरफ़ॉर्म: मुझे यह नहीं लगता कि केवल कॉल के लिए उपयोग किए जाने वाले एक अस्थायी चर का नाम बदलने के लिए बहुत मुश्किल है। यदि कोई एनम नाम बदला गया है, तो यह और भी बेहतर है, क्योंकि कॉल कोड अब नहीं चलेगा और आपके चेहरे में एक त्रुटि फेंक देगा। यदि फ़ंक्शन की कार्यक्षमता मौलिक रूप से एक एनम एक्सटेंशन द्वारा बदल दी जाती है, तो आपको आगे की शुद्धता के लिए सभी कॉल को फिर से चालू करना होगा, वैसे भी, आप आशा पर कार्यक्रम करते हैं, तर्क पर नहीं। यहां तक कि नहीं मान बदलने, जैसे negating के बारे में सोचना preventUndoकरने के लिए allowUndoहस्ताक्षर में ...
सुरक्षित

4
@ superM कोड के साथ टिप्पणियों को सिंक में रखना बहुत परेशानी वाला है, क्योंकि विसंगतियों के लिए आपकी खोज में आपके कंपाइलर की कोई मदद नहीं की गई है।
बुहब

7
"... आपको अपनी आईडीई पर भरोसा है कि आपको कॉल की गई विधि के हस्ताक्षर देने के लिए" - जब आप कोड लिख रहे हों, तो यह उपयोगी है, लेकिन जब आप इसे पढ़ रहे हों तो ऐसा न हो। जब मैं एक कक्षा के लिए कोड पढ़ता हूं, तो मैं यह जानना चाहता हूं कि यह क्या कर रहा है। यदि आपको पठनीयता के लिए IDE पर निर्भर रहना पड़ता है, तो आपका कोड स्व-दस्तावेजीकरण नहीं है।
फिल

20

न तो, आप बूलियन झंडे के साथ तरीके नहीं लिखना चाहिए।

रॉबर्ट सी। मार्टिन के हवाले से उनकी किताब क्लीन कोड (आईएसबीएन -13 978-0-13-235088-4) में कहा गया है, "एक समारोह में बूलियन पास करना वास्तव में भयानक अभ्यास है।"

उसे विरोधाभास करने के लिए, तर्क यह है कि आपके पास एक सही / गलत स्विच होने का तथ्य यह है कि आपकी विधि सबसे अधिक संभावना है कि आप दो अलग-अलग चीजें कर रहे हैं (जैसे "पूर्ववत कुछ करें" और "पूर्ववत कुछ न करें"), और इसलिए ऐसा होना चाहिए दो अलग-अलग तरीकों में विभाजित (जो आंतरिक रूप से एक ही बात कह सकते हैं)।

DoSomething()
{...

DoSomethingUndoable()
{....

7
उस तर्क से मेरे एकल हॉटडॉग निर्माता को लगभग 16 विभिन्न तरीकों की आवश्यकता होगी: HotDogWithMustardRelishKrautOnion (), HotDogWithMustardNorelishKrautOnion (), और इसी तरह। या, यह एक साधारण HotDogWithOptions (int विकल्प) हो सकता है, जिसमें मैं विकल्पों को थोड़ा क्षेत्र के रूप में व्याख्या करता हूं, लेकिन फिर हम एक विधि पर वापस आते हैं जो कई कथित रूप से अलग-अलग चीजें करता है। इसलिए यदि मैं पहले विकल्प के साथ जाता हूं, तो क्या मुझे एक बड़ी शर्त लिखनी होगी कि किस निर्माता को कॉल करने के लिए उन चीजों के आधार पर कॉल किया जाए जो अन्यथा बूलियन पैरामीटर थीं? और यदि Q एक int का उपयोग करता है, तो यह A, Q का उत्तर नहीं देता है
Caleb

4
सभी उत्तरों को पढ़ने और अपने कोड को देखने के बाद मैं इस निष्कर्ष पर पहुंच रहा हूं कि यह करने का सही तरीका है। doSomethingUndoable()परिवर्तनों को पकड़ सकता है और फिर कॉल कर सकता हैdoSomething()
मेथोडोफिकेशन

1
इसलिए अगर मेरे पास एक फ़ंक्शन है जो बहुत सारी प्रसंस्करण करता है और एक ईमेल भेजने का विकल्प होता है जब यह किया जाता है, तो मुझे एक बूलियन तर्क नहीं होना चाहिए जो ईमेल को भेजने से रोक सकता है, मुझे एक अलग फ़ंक्शन बनाना चाहिए?
यकजट

2
@ कालेब इस मामले में मैं या तो एक हॉटडॉग बनाऊंगा और एक-एक करके सामग्री जोड़ूंगा , या जोरदार टाइप की हुई भाषा में मैं एक ऑब्जेक्ट हॉटडॉगसेटिंग पास करूंगा जिसमें मैंने सभी बूलियन झंडे लगाए होंगे। मेरे पास 15 अलग-अलग सच्चे / झूठे झंडे नहीं होंगे जो बनाए रखने के लिए एक बुरा सपना होगा। याद रखें कि कोड रखरखाव के बारे में लिख रहा है न कि क्योंकि आवेदन की लागत का 80% था। var hd = MakeHotDog (); hd.Add (प्याज); ...
Nick B.

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

5

जब आप दो वर्गों को देखते हैं कि वे कितने युग्मित हैं, तो श्रेणियों में से एक डेटा युग्मन है , जो एक वर्ग को दूसरे वर्ग की कॉलिंग विधियों में कोड करने के लिए संदर्भित करता है और सिर्फ डेटा में गुजरता है, जैसे कि आप किस महीने के लिए रिपोर्ट चाहते हैं, और दूसरा श्रेणी नियंत्रण युग्मन , कॉल करने के तरीके और कुछ है जो विधि के व्यवहार को नियंत्रित करता है में गुजर रहा है। कक्षा में मेरे द्वारा उपयोग किया जाने वाला उदाहरण एक verboseध्वज या reportTypeध्वज है, लेकिन preventUndoयह भी एक महान उदाहरण है। जैसा कि आपने अभी-अभी प्रदर्शित किया है, नियंत्रण युग्मन से कॉलिंग कोड पढ़ना और समझना मुश्किल हो जाता है कि क्या हो रहा है। यह कॉलिंग कोड को उन परिवर्तनों के प्रति संवेदनशील बनाता है जो doSomething()पूर्ववत और संग्रह दोनों को नियंत्रित करने के लिए एक ही ध्वज का उपयोग करते हैं, या किसी अन्य पैरामीटर को जोड़ते हैंdoSomething() इस प्रकार अपने कोड को तोड़ना, और इसी तरह से नियंत्रण करना।

समस्या यह है कि कोड बहुत कसकर युग्मित है। व्यवहार को नियंत्रित करने के लिए एक बूल पास करना, मेरी राय में, एक खराब एपीआई का संकेत है। यदि आप एपीआई के मालिक हैं, तो इसे बदल दें। दो तरीके, doSomething()और doSomethingWithUndo(), बेहतर होगा। यदि आपके पास यह नहीं है, तो अपने द्वारा किए गए कोड में स्वयं दो रैपर विधियां लिखें, और उनमें से एक कॉल doSomething(true)और दूसरा कॉल करें doSomething(false)


4

यह तर्कों की भूमिका को परिभाषित करने के लिए फोन करने वाले की भूमिका नहीं है। मैं हमेशा इनलाइन संस्करण के लिए जाता हूं, और यदि मुझे संदेह है तो कॉल किए गए फ़ंक्शन के हस्ताक्षर की जांच करें।

मौजूदा दायरे में उनकी भूमिका के लिए परिवर्तनीय का नाम दिया जाना चाहिए। वह दायरा नहीं जहाँ उन्हें भेजा जाता है।


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

4

मैं जावास्क्रिप्ट में क्या करूंगा कि फंक्शन एक वस्तु को केवल पैरामीटर के रूप में कुछ इस तरह ले जाए:

function doSomething(settings) {
    var preventUndo = settings.hasOwnProperty('preventUndo') ? settings.preventUndo : false;
    // Deal with preventUndo in the normal way.
}

फिर इसके साथ कॉल करें:

doSomething({preventUndo: true});

हा !!! हम दोनों ने एक doSomething(x)विधि बनाई ! योग्य ... मैंने अब तक आपके पोस्ट को नोटिस भी नहीं किया था।
मांस

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

1
अपने कोड का दस्तावेज़ दें। वही बाकी सब करते हैं। यह आपके कोड को पढ़ना आसान बनाता है, यह लिखना केवल एक बार ही होता है।
ridecar2

1
@NickB। सम्मेलन शक्तिशाली है। यदि आपका अधिकांश कोड तर्कों के साथ वस्तुओं को स्वीकार करता है तो यह स्पष्ट है।
21

4

मैं स्वयं स्पष्टता में मदद करने के लिए भाषा सुविधाओं का लाभ उठा रहा हूं। उदाहरण के लिए C # में आप नाम से पैरामीटर निर्दिष्ट कर सकते हैं:

 CallSomething(name: "So and so", age: 12, description: "A random person.");

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

function doSomething(args) { /*...*/ }

doSomething({ name: 'So and so', age: 12, description: 'A random person.' });

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


1
यही कारण है कि शिथिल टाइप की भाषाओं के लिए "नकारात्मक" है। आप वास्तव में कुछ सत्यापन के बिना एक हस्ताक्षर लागू नहीं कर सकते। मुझे नहीं पता था कि आप जेएस में इस तरह के नाम जोड़ सकते हैं।
जेम्स पी।

1
@JamesPoulson: आपको शायद पता था कि आप JS में ऐसा कर सकते हैं और बस इसका एहसास नहीं था। यह सब JQuery में खत्म हो गया है: $.ajax({url:'', data:''})आदि आदि
blesh

सच। यह पहली नजर में असामान्य लगता है लेकिन यह इनलाइन छद्म वस्तुओं के समान है जो कुछ भाषाओं में मौजूद हो सकती हैं।
जेम्स पी।

3

मुझे लगता है कि यह सबसे सरल और पढ़ने में आसान है:

enum Undo { ALLOW, PREVENT }

doSomething(Undo u) {
    if (Undo.ALLOW == u) {
        // save stuff to undo later.
    }
    // do your thing
}

doSomething(Undo.ALLOW);

मेनमा ऐसा नहीं है। हम असहमत होने के लिए सहमत हो सकते हैं, या हम एक समाधान का उपयोग कर सकते हैं जो जोशुआ बलोच प्रस्तावित करता है:

enum Undo {
    ALLOW {
        @Override
        public void createUndoBuffer() {
            // put undo code here
        }
    },
    PREVENT {
        @Override
        public void createUndoBuffer() {
            // do nothing
        }
    };

    public abstract void createUndoBuffer();
}

doSomething(Undo u) {
    u.createUndoBuffer();
    // do your thing
}

अब यदि आप कभी भी एक Undo.LIMITED_UNDO जोड़ते हैं, तो आपका कोड तब तक संकलित नहीं होगा जब तक आप createUndoBuffer () विधि को लागू नहीं करते हैं। और doSomething () में ऐसा नहीं है अगर (Undo.ALLOW == u)। मैंने इसे दोनों तरीकों से किया है और दूसरी विधि बहुत हैवीवेट है और समझने में थोड़ी मुश्किल है जब पूर्ववत एनम पृष्ठों और कोड के पन्नों में फैलता है, लेकिन यह आपको लगता है। मैं आमतौर पर सरल विधि के साथ एक साधारण बूलियन को बदलने के लिए 2-वैल्यू एनम के साथ छड़ी करता हूं जब तक कि मेरे पास बदलने का कारण नहीं है। जब मैं तीसरा मूल्य जोड़ता हूं, तो मैं अपनी आईडीई का उपयोग "फाइंड-यूजेज" के लिए करता हूं और फिर सब कुछ ठीक करता हूं।


2

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

मैं दो विकल्पों के बारे में सोच सकता हूं जिनमें एक अतिरिक्त चर शामिल नहीं है:

1. एक अतिरिक्त टिप्पणी का उपयोग करें

doSomething(/* preventUndo */ true);

2. बूलियन के बजाय दो-मूल्यवान एनम का उपयोग करें

enum Options
{
    PreventUndo,
    ...
}

...

doSomething(PreventUndo);

आप वैकल्पिक 2 का उपयोग कर सकते हैं यदि आपकी भाषा enums का समर्थन करती है।

संपादित करें

बेशक, नामित तर्कों का उपयोग करना भी एक विकल्प है, अगर आपकी भाषा उनका समर्थन करती है।

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

if (preventUndo)
{
    ...
}

आपके पास

if (undoOption == PreventUndo)
{
    ...
}

या

switch (undoOption)
{
  case PreventUndo:
  ...
}

और यहां तक ​​कि अगर यह थोड़ा अधिक टाइपिंग है, तो याद रखें कि कोड एक बार लिखा गया है और कई बार पढ़ा गया है, इसलिए छह महीने बाद एक अधिक पठनीय कोड खोजने के लिए यह अब थोड़ा अधिक टाइप कर सकता है।


2

मैं @GlenPeterson ने क्या कहा:

doSomething(Undo.ALLOW); // call using a self evident enum

लेकिन यह भी उल्लेख करना निम्न होगा क्योंकि यह मुझे लगता है कि केवल दो सकारात्मकताएं हैं (सच्ची या झूठी)

//Two methods    

doSomething()  // this method does something but doesn't prevent undo

doSomethingPreventUndo() // this method does something and prevents undo

2
अच्छा विचार - मैंने ऐसा नहीं सोचा था। जब आपको doSomething (String, String, String, boolean, boolean, boolean) जैसे और अधिक जटिल हो जाते हैं तो नामांकित स्थिरांक एकमात्र उचित समाधान हैं। खैर, जोश बलोच एक कारखाने और निर्माता के रूप में वस्तु का सुझाव देते हैं: MyThingMaker thingMaker = MyThingMaker.new (); thingMaker.setFirstString ( "हाय"); thingMaker.setSecondString ( "वहाँ"); आदि ... बात t = thingMaker.makeIt (); t.doSomething (); यह सिर्फ एक बहुत अधिक काम है, इसलिए यह बेहतर होना चाहिए था।
ग्लेनपेटर्सन

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

@GlenPeterson एक कारखाना एक संभावना है और जावास्क्रिप्ट (ओपी द्वारा उल्लिखित) में संभव है।
जेम्स पी।

2

जब से आप मुख्य रूप से जावास्क्रिप्ट के बारे में पूछ रहे हैं, तो कॉफ़ीस्क्रिप्ट का उपयोग करके आप सिंटैक्स जैसे एक नामित तर्क दे सकते हैं, सुपर आसान:

# declare method, ={} declares a default value to prevent null reference errors
doSomething = ({preventUndo} = {}) ->
  if preventUndo
    undo = no
  else
    undo = yes

#call method
doSomething preventUndo: yes
#or 
doSomething(preventUndo: yes)

के लिए संकलित करता है

var doSomething;

doSomething = function(_arg) {
  var preventUndo, undo;
  preventUndo = (_arg != null ? _arg : {}).preventUndo;
  if (preventUndo) {
    return undo = false;
  } else {
    return undo = true;
  }
};

doSomething({
  preventUndo: true
});

doSomething({
  preventUndo: true
});

संभावनाओं को आज़माने के लिए http://js2cfish.org/ पर कुछ मज़े करें


मैं केवल कॉफीस्क्रिप्ट का उपयोग करता हूं जब मुझे जावास्क्रिप्ट के ओओपी पागलपन से बचने की आवश्यकता होती है। यह एक अच्छा समाधान है जिसका उपयोग मैं अकेले करते समय कर सकता हूं, यह सहकर्मी के लिए कठिन होगा कि मैं पठनीयता के लिए बूलियन के बजाय किसी वस्तु को पास कर रहा हूं!
मेथोडिफिकेशन

1

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

var doSomethingOptions = new Array();

doSomethingOptions["PREVENTUNDO"] = true;
doSomethingOptions["TESTMODE"] = false;

doSomething( doSomethingOptions );

// ...

function doSomething( doSomethingOptions ){
    // Check for null here
    if( doSomethingOptions["PREVENTUNDO"] ) // ...
}

मुझे लगता है कि यह दृढ़ता से टाइप की गई पृष्ठभूमि से किसी का पलटा है और शायद इतना व्यावहारिक न हो लेकिन मौलिकता के लिए इस पर विचार करें।

एक और संभावना एक वस्तु है और जावास्क्रिप्ट में भी संभव है। मुझे यकीन नहीं है कि यह 100% सही है। आगे की प्रेरणा के लिए फ़ैक्टरी जैसे पैटर्न पर एक नज़र डालें।

function SomethingDoer( preventUndo ) {
    this.preventUndo = preventUndo;
    this.doSomething = function() {
            if( this.preventUndo ){
                    // ...
            }
    };
}

mySomethingDoer = new SomethingDoer(true).doSomething();

1
मुझे लगता है कि यह doSomethingOptions.PREVENTUNDOऐरे एक्सेस नोटेशन के बजाय डॉट-नोटेशन ( ) में बेहतर लिखा जा सकता है।
पाओलो एबरमन

1

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

मुझे लगता है कि यह नोट करना उपयोगी है कि यह समस्या ज्यादातर तब होती है जब प्रोग्रामिंग भाषा सी # 4 और पायथन जैसे नामित तर्कों / कीवर्ड तर्कों का समर्थन करती है, या जहां विधि के नाम को स्मालटॉक या ऑब्जेक्टिव-सी की तरह विधि के नाम में वर्गीकृत किया जाता है।

उदाहरण:

// C# 4
foo.doSomething(preventUndo: true);
# Python
foo.doSomething(preventUndo=True)
// Objective-C
[foo doSomethingWith:bar shouldPreventUndo:YES];

0

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

जब भी किसी को फंक्शन के लिए बूलियन तर्क आता है, तो उन्हें कोड को ऐसे मोड़ना होगा कि वे बूलियन तर्क बिल्कुल न लिखें।


तो आप एक फ़ंक्शन को दो कार्यों में बूलियन तर्क के साथ बदल सकते हैं जो केवल उनके कोड के छोटे हिस्से में भिन्न होता है (जहां मूल में एक होगा if(param) {...} else {...})?
पाओलो एबरमन

-1
int preventUndo = true;
doSomething(preventUndo);

निम्न लवलीन भाषाओं के लिए एक अच्छा संकलक जैसे कि C ++ नीचे दिए गए 2 लाइन के मशीन कोड को अनुकूलित करेगा:

doSomething(true); 

इसलिए यह प्रदर्शन में कोई फर्क नहीं पड़ता, लेकिन पठनीयता को बढ़ाएगा।

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

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