क्या किसी भी चीज़ के लिए एक फ़ंक्शन लिखना हमेशा एक सर्वोत्तम अभ्यास होता है जिसे दो बार दोहराने की आवश्यकता होती है?


131

जब मैं दो बार से अधिक कुछ करने की आवश्यकता होती है, तो मैं एक फ़ंक्शन लिखने के लिए इंतजार नहीं कर सकता। लेकिन जब यह उन चीजों की बात आती है जो केवल दो बार दिखाई देती हैं, तो यह थोड़ा और मुश्किल है।

कोड के लिए जिसे दो से अधिक लाइनों की आवश्यकता है, मैं एक फ़ंक्शन लिखूंगा। लेकिन जब चीजों का सामना करना पड़ रहा है:

print "Hi, Tom"
print "Hi, Mary"

मुझे लिखने में संकोच है:

def greeting(name):
    print "Hi, " + name

greeting('Tom')
greeting('Mary')

दूसरा बहुत ज्यादा लगता है, है ना?


लेकिन क्या होगा अगर हमारे पास:

for name in vip_list:
    print name
for name in guest_list:
    print name

और यहाँ विकल्प है:

def print_name(name_list):
    for name in name_list:
        print name

print_name(vip_list)
print_name(guest_list)

चीजें मुश्किल हो जाती हैं, नहीं? अब फैसला करना मुश्किल है।

इस बारे में आपकी क्या राय है?


145
मैं इलाज करता हूं alwaysऔर neverलाल झंडे के रूप में। "संदर्भ" नाम की एक चीज है, जहां नियम alwaysऔर neverनियम, भले ही सामान्य रूप से अच्छे हों, यह उचित नहीं हो सकता है। सॉफ्टवेयर डेवलपर्स से सावधान रहें जो निरपेक्षता में सौदा करते हैं। ;)
async

7
अपने पिछले उदाहरण में आप कर सकते हैं: from itertools import chain; for name in chain(vip_list, guest_list): print(name)
बकुरीउ १३'१५:२६:

14
@ user16547 हम उन 'सिथवेयर डेवलपर्स' को कहते हैं!
ब्रायन

6
टिम पीटर्स द्वारा पायथन के ज़ेन से:Special cases aren't special enough to break the rules. Although practicality beats purity.
ज़ेनॉन

3
यह भी विचार करें कि क्या आप "नम कोड" या "ड्राई कोड" देखना चाहते हैं, तो stackoverflow.com/questions/6453235/…
Ian

जवाबों:


201

यद्यपि यह एक फ़ंक्शन को विभाजित करने का निर्णय लेने में एक कारक है, लेकिन कुछ दोहराया जाने की संख्या केवल कारक नहीं होनी चाहिए। यह अक्सर कुछ के लिए एक फ़ंक्शन बनाने के लिए समझ में आता है जिसे केवल एक बार निष्पादित किया जाता है । आम तौर पर, आप एक फ़ंक्शन को विभाजित करना चाहते हैं जब:

  • यह प्रत्येक व्यक्तिगत अमूर्त परत को सरल करता है।
  • स्प्लिट-ऑफ फ़ंक्शंस के लिए आपके पास अच्छे, सार्थक नाम हैं, इसलिए आपको यह समझने के लिए आमतौर पर अमूर्त परतों के बीच कूदने की ज़रूरत नहीं है कि क्या चल रहा है।

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


यह वह बिंदु है जो मुझे रॉबर्टहार्वे के उत्तर में याद आता है।
Doc Brown

1
वास्तव में। मैं अक्सर जटिल कार्यों को इनबिल्ड सबरूटीन्स में विभाजित करता हूं - कोई परफेक्ट हिट नहीं, बल्कि क्लीन। अनाम स्कोप्स भी अच्छे हैं।
इमललेट

3
इसमें भी गुंजाइश की बात है। यह शायद मतलब नहीं है एक लिखने के लिए print_name (NAME_LIST) समारोह है कि एक पूरा वर्ग या पूरे मॉड्यूल देख सकते हैं, लेकिन यह हो सकता है मतलब एक साफ करने के लिए एक समारोह के भीतर एक स्थानीय समारोह बनाने के लिए (अभी भी इस मामले में एक खंड) बार-बार कोड की कुछ लाइनें।
जोशुआ टेलर

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

1
+1 सिर्फ इसके लिए अक्सर कुछ के लिए एक फ़ंक्शन बनाने के लिए समझ में आता है जिसे केवल एक बार निष्पादित किया जाता है। मुझे एक बार पूछा गया था कि एक रॉकेट इंजन के व्यवहार को मॉडल बनाने वाले फ़ंक्शन के लिए परीक्षण कैसे डिज़ाइन किया जाए। 90 के दशक में उस फ़ंक्शन की चक्रीय जटिलता थी, और यह 90 कुछ मामलों के साथ एक स्विच स्टेटमेंट नहीं था (बदसूरत, लेकिन परीक्षण योग्य)। इसके बजाय यह इंजीनियरों द्वारा लिखा गया एक जटिल गड़बड़ था और पूरी तरह से अप्राप्य था। मेरी प्रतिक्रिया बस यही थी, कि यह अप्राप्य था और इसे फिर से लिखने की आवश्यकता थी। उन्होंने मेरी सलाह का पालन किया!
डेविड हैमेन

104

केवल अगर आकस्मिक के बजाय दोहराव जानबूझकर है

या, एक और तरीका रखो:

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


यहाँ पर क्यों:

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

अंगूठे का नियम:

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


12
+1 मुझे लगता है कि यह सबसे महत्वपूर्ण विचार है। कोई भी रिफ्लेक्टर कोड उनके परिवर्तन की उम्मीद नहीं करता है, इसलिए विचार करें कि आपके परिवर्तन कोड में भविष्य के परिवर्तनों को कैसे प्रभावित करेंगे।
योनीलवी

2
यह रूबी है, लेकिन अड्डी ग्रिम से संयोग दोहराव के बारे में यह पेंच अभी भी सवाल से संबंधित है: youtube.com/watch?v=E4FluFOC1zM
DGM

60

नहीं, यह हमेशा एक सर्वोत्तम अभ्यास नहीं है।

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

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


58
कोड पठनीयता सबसे महत्वपूर्ण है।
टॉम रॉबिन्सन

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

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

19
Why take the performance hit of a function call when you don't get any significant benefit by doing so?क्या प्रदर्शन हिट हुआ? सामान्य स्थिति में छोटे कार्य निष्फल हो जाते हैं और बड़े कार्यों के लिए ओवरहेड नगण्य हो जाता है। CPython शायद इनलाइन नहीं करता है, लेकिन कोई भी इसे प्रदर्शन के लिए उपयोग नहीं करता है। मैं भी line by line code...थोड़ा सवाल करता हूं । यदि आप अपने मस्तिष्क में निष्पादन का अनुकरण करना चाहते हैं तो यह आसान है। लेकिन एक डीबगर बेहतर काम करेगा, और इसके निष्पादन के बाद लूप के बारे में कुछ साबित करने की कोशिश करेगा, जैसे कि उन सभी पर ध्यान देकर पूर्णांकों के बारे में एक कथन को साबित करने की कोशिश करना।
डोभाल

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

25

अपने विशेष उदाहरण में एक फ़ंक्शन बनाने से ओवरकिल लग सकता है; इसके बजाय मैं सवाल पूछूंगा: क्या यह संभव है कि यह विशेष ग्रीटिंग भविष्य में बदल जाएगा? ऐसा कैसे?

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

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

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


GREET_OPEN लगातार उपयोग करने से सभी संभावित अभिवादन एक ही क्रम में होते हैं। किसी ऐसे व्यक्ति से शादी करना जिसकी मातृभाषा अंग्रेजी के विपरीत लगभग सब कुछ करती है, मुझे इस धारणा का लाभ देती है।
लोरेन Pechtel

22

व्यक्तिगत रूप से मैंने तीन का नियम अपनाया है - जिसे मैं YAGNI कहकर उचित ठहराऊंगा । अगर मुझे उस कोड को लिखने के बाद कुछ करने की आवश्यकता होती है, तो दो बार मैं सिर्फ कॉपी / पेस्ट कर सकता हूं (हाँ मैं सिर्फ कॉपी / पेस्ट करने के लिए स्वीकार किया था!) ​​क्योंकि मुझे फिर से इसकी आवश्यकता नहीं है, लेकिन अगर मुझे ऐसा करने की आवश्यकता है फिर से बात करता हूं और फिर उस चंक को अपने तरीके से निकालता हूं, मैंने खुद को, यह प्रदर्शित किया है कि मुझे फिर से इसकी आवश्यकता होगी

मैं इस बात से सहमत हूं कि कार्ल बेवफेल्ट और रॉबर्ट हार्वे ने जो कहा है और जो वे कह रहे हैं, उसकी मेरी व्याख्या है कि ओवरराइडिंग नियम पठनीयता है। यदि यह मेरे कोड को पढ़ने में आसान बनाता है, तो एक फ़ंक्शन बनाने पर विचार करें, DRY और SLAP जैसी चीजों को ध्यान में रखें । अगर मैं अपने फंक्शन में एब्सट्रैक्शन के बदलते स्तर से बच सकता हूं, तो मुझे लगता है कि मेरे सिर को मैनेज करना आसान है, इसलिए फंक्शन्स के बीच नहीं कूदना (अगर मैं समझ नहीं पा रहा हूं कि फंक्शन क्या होता है इसका नाम पढ़कर पता चलता है) मानसिक प्रक्रियायें।
इसी तरह कार्यों और इनलाइन कोड जैसे कि print "Hi, Tom"मेरे लिए काम के बीच संदर्भ स्विच नहीं करने के लिए , इस मामले में मैं एक समारोह iff निकाल सकते हैंPrintNames() मेरे कुल समारोह के बाकी ज्यादातर फ़ंक्शन कॉल थे।


3
C2 विकी के तीन के नियम पर एक अच्छा पेज है: c2.com/cgi/wiki?RuleOfThree
pimlottc

13

यह शायद ही कभी स्पष्ट रूप से कटा हो, इसलिए आपको विकल्प चुनने की आवश्यकता है:

  • समय सीमा (फिक्सिंग सर्वर रूम ASAP)
  • कोड पठनीयता (पसंद को किसी भी तरह से प्रभावित कर सकती है)
  • साझा तर्क का स्तर अमूर्त (ऊपर से संबंधित)
  • पुन: उपयोग की आवश्यकता (अर्थात ठीक वही तर्क महत्वपूर्ण है, या अभी सुविधाजनक है)
  • साझा करने में कठिनाई (यहां व्हाइर पाइथन चमकता है, नीचे देखें)

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

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

इसलिए, स्थानीय तर्कों से एक सूची बनाकर, उदाहरण के लिए, स्थानीय रूप से तर्क का पुन: उपयोग करने पर विचार करें:

def foo():
    for name_list in (vip_list, guest_list): # can be list of tuples, for many args
        for name in name_list:
            print name

यदि आप कई तर्कों की आवश्यकता है, तो आप टुपल्स के ट्यूल का उपयोग कर सकते हैं, और इसे सीधे लूप में विभाजित कर सकते हैं:

def foo2():
    for header, name_list in (('vips': vip_list), ('people': guest_list)): 
        print header + ": "
        for name in name_list:
            print name

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

def foo():
    def print_name(name_list):
        for name in name_list:
            print name

    print_name(vip_list)
    print_name(guest_list)

कार्य विशेष रूप से तब बेहतर होते हैं जब आपको बीच में तर्क को निरस्त करने की आवश्यकता होती है (जैसे कि रिटर्न का उपयोग), क्योंकि ब्रेक या अपवाद अनावश्यक रूप से चीजों को अव्यवस्थित कर सकते हैं।

या तो एक ही तर्क, IMO को दोहराने से बेहतर है, और एक वैश्विक / वर्ग फ़ंक्शन की घोषणा करने की तुलना में कम अव्यवस्था है जो केवल एक कॉलर द्वारा उपयोग किया जाता है (यद्यपि दो बार)।


मैंने इस उत्तर को देखने से पहले नए फ़ंक्शन के दायरे के बारे में इसी तरह की टिप्पणी पोस्ट की । मुझे खुशी है कि प्रश्न के उस पहलू को संबोधित करने वाला एक उत्तर है।
जोशुआ टेलर

1
+1 - यह शायद उस तरह का उत्तर नहीं है जिसे ओपी खोज रहा है, बल्कि कम से कम उस तरह के प्रश्न के बारे में जो उसने पूछा है, मुझे लगता है कि यह सबसे समझदार प्रतिक्रिया है। यह इस तरह की बात है जो शायद आपके लिए भाषा में, किसी तरह बेक की जाएगी।
पैट्रिक कॉलिन्स

@PatrickCollins: वोट के लिए धन्यवाद! :) मैंने उत्तर को और अधिक पूर्ण बनाने के लिए कुछ विचार जोड़े हैं।
मैके

9

सभी सर्वोत्तम प्रथाओं का एक विशेष कारण है, जिसे आप ऐसे प्रश्न का उत्तर देने के लिए संदर्भित कर सकते हैं। जब आप एक संभावित भावी परिवर्तन का अर्थ है कि अन्य घटकों के लिए भी परिवर्तन का अर्थ है, तो आप हमेशा लहर से बचना चाहिए।

इसलिए अपने उदाहरण में: यदि आप मानते हैं कि आपके पास एक मानक ग्रीटिंग है और आप यह सुनिश्चित करना चाहते हैं कि यह सभी लोगों के लिए समान हो, तो लिखें

def std_greeting(name):
    print "Hi, " + name

for name in ["Tom", "Mary"]:
    std_greeting(name)   # even the function call should be written only once

अन्यथा, आपको ध्यान देना होगा और दो स्थानों पर मानक ग्रीटिंग को बदलना होगा, अगर यह परिवर्तन होता है।

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

print "Hi, Tom"
print "Hello, Mary"

अपने दूसरे भाग के लिए, यह तय करने के लिए कि कार्यों में "पैकेज" कितना है, संभवतः दो कारकों पर निर्भर करता है:

  • पठनीयता के लिए ब्लॉक छोटे रखें
  • ब्लॉकों को पर्याप्त रूप से बड़ा रखें ताकि केवल कुछ ब्लॉकों में परिवर्तन हो। कॉलिंग पैटर्न को ट्रैक करना कठिन होने के कारण बहुत अधिक क्लस्टर की आवश्यकता नहीं है।

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


बस अपने पाश पर विचार करते हुए एक बेवकूफ नाइटपार्टिंग - अगर वास्तव में केवल कठिन-कोडित नामों को पुनरावृति करने के लिए एक मुट्ठी भर होने की आवश्यकता है, और हम उन्हें बदलने की उम्मीद नहीं करते हैं, तो मैं तर्क दूंगा कि यह एक का उपयोग नहीं करने के लिए थोड़ा अधिक उपयुक्त है सूची। for name in "Tom", "Mary": std_greeting(name)
yoniLavi

खैर, जारी रखने के लिए कोई कह सकता है कि एक हार्ड-कोडित सूची कोड के बीच में दिखाई नहीं देने वाली है और वैसे भी एक चर होगी :) लेकिन सही है, मैं वास्तव में भूल गया कि आप वहां ब्रेस को छोड़ सकते हैं।
गैरेनुक

5

नामित स्थिरांक और कार्यों का सबसे महत्वपूर्ण पहलू इतना नहीं है कि वे टाइपिंग की मात्रा को कम करते हैं, बल्कि यह कि वे विभिन्न स्थानों पर "संलग्न" करते हैं जहां उनका उपयोग किया जाता है। अपने उदाहरण के संबंध में, चार परिदृश्यों पर विचार करें:

  1. यह उसी तरह से दोनों बधाई बदलने के लिए आवश्यक है, [करने के लिए जैसे Bonjour, Tomऔर Bonjour, Mary]।

  2. एक अभिवादन को बदलना आवश्यक है लेकिन दूसरे को छोड़ दें क्योंकि यह [उदा ] Hi, Tomऔर है Guten Tag, Mary

  3. दोनों अभिवादनों को अलग-अलग [जैसे Hello, Tomऔर Howdy, Mary] बदलना आवश्यक है ।

  4. न तो ग्रीटिंग को कभी बदलने की जरूरत है।

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

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


मुझे यह उत्तर पसंद है क्योंकि (इस सरल उदाहरण के लिए कम से कम), आप कुछ गेम थ्योरी के माध्यम से पसंद की गणना कर सकते हैं।
रबरडैक

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

@ रबरडैक: ... अगर दो में से कुछ हैं और वे मेल खाते हैं, तो यह जानना महत्वपूर्ण है कि क्या एक को बदलना दूसरे को स्थिर रखना चाहिए, या रिश्ते को स्थिर रखना चाहिए (मतलब दूसरे का मूल्य बदल जाएगा)। मैं अक्सर मूल्यों को स्थिर रखने के फायदों के लिए दिए गए महान वजन को देखता हूं , लेकिन रिश्तों के महत्व को देखते हुए बहुत कम वजन ।
सुपरकैट

मैं पूरी तरह से सहमत। मैं सिर्फ इस बात पर ध्यान दे रहा था कि पारंपरिक ज्ञान इसे DRY के लिए कैसे कहता है, लेकिन सांख्यिकीय रूप से , यह अधिक संभावना है कि बाद में दोहराया गया कोड दोहराया नहीं जाएगा। आपको मूल रूप से 2 से 1 ऑड मिला है।
रबरडैक

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

5

मुझे लगता है कि आपके पास एक प्रक्रिया बनाने का एक कारण होना चाहिए। एक प्रक्रिया बनाने के लिए कई कारण हैं। मुझे लगता है कि सबसे महत्वपूर्ण हैं:

  1. मतिहीनता
  2. प्रतिरूपकता
  3. कोड नेविगेशन
  4. निरंतरता अद्यतन करें
  5. प्रत्यावर्तन
  6. परिक्षण

मतिहीनता

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

प्रतिरूपकता

मॉड्यूल में कोड व्यवस्थित करने के लिए प्रक्रियाओं का उपयोग किया जा सकता है। मॉड्यूल को अक्सर अलग से इलाज किया जा सकता है। उदाहरण के लिए, अलग से बनाया और परीक्षण किया गया।

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

कोड नेविगेशन

बड़ी प्रणालियों में, किसी विशेष प्रणाली के व्यवहार से जुड़े कोड को ढूंढना चुनौतीपूर्ण हो सकता है। पुस्तकालयों, मॉड्यूल और प्रक्रियाओं के भीतर कोड का पदानुक्रमित संगठन इस चुनौती के साथ मदद कर सकता है। विशेष रूप से यदि आप a) सार्थक और पूर्वानुमेय नामों के तहत कार्यक्षमता को व्यवस्थित करने का प्रयास करते हैं b) एक दूसरे के पास समान कार्यक्षमता से संबंधित प्रक्रियाओं को रखें।

निरंतरता अद्यतन करें

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

ध्यान दें कि आपको कार्यक्रम में कार्य और योग्यता के आधार पर प्रक्रियाओं को व्यवस्थित करना चाहिए। इस आधार पर नहीं कि इस समय कोड के दो बिट्स समान हैं।

प्रत्यावर्तन

पुनरावर्तन का उपयोग करने के लिए आवश्यक है कि आप प्रक्रियाएँ बनाएँ

परिक्षण

आप आमतौर पर एक दूसरे से स्वतंत्र रूप से प्रक्रियाओं का परीक्षण कर सकते हैं। स्वतंत्र रूप से एक प्रक्रिया के शरीर के विभिन्न भागों का परीक्षण करना अधिक कठिन होता है, क्योंकि आपको आमतौर पर प्रक्रिया के पहले भाग को दूसरे भाग से पहले निष्पादित करना होता है। यह अवलोकन अक्सर कार्यक्रमों के व्यवहार को निर्दिष्ट / सत्यापित करने के लिए अन्य तरीकों पर भी लागू होता है।

निष्कर्ष

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


4

आपके द्वारा दिए गए मामलों में से कोई भी रिफैक्टिंग के लायक नहीं है।

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

मेरा सुझाव है कि आप हमेशा कोड को अलग करने के तरीकों की तलाश करें:

  1. एक पहचान योग्य, सार्थक कार्य है जिसे आप अलग कर सकते हैं, और

  2. भी

    ए। कार्य व्यक्त करना जटिल है (आपके लिए उपलब्ध कार्यों को ध्यान में रखते हुए) या

    ख। कार्य एक से अधिक बार किया जाता है, और आपको यह सुनिश्चित करने के तरीके की आवश्यकता होती है कि इसे दोनों स्थानों पर एक ही तरह से बदल दिया जाए,

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

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

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

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

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

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


3

सामान्य तौर पर मैं रॉबर्ट हार्वे के साथ सहमत हूं, लेकिन कार्यों में कार्यक्षमता को विभाजित करने के लिए एक मामला जोड़ना चाहता था। पठनीयता में सुधार करने के लिए। एक मामले पर विचार करें:

def doIt(smth,smthElse)
    for x in getDataFromSomething(smth,smthElse):
        if not check(x,smth):
            continue
        process(x,smthElse)
        store(x) 

भले ही उन फ़ंक्शन कॉल का उपयोग कहीं और नहीं किया जाता है, लेकिन पठनीयता में महत्वपूर्ण लाभ होता है यदि सभी 3 फ़ंक्शन काफी लंबे होते हैं और इसमें एनआईटी लूप आदि होते हैं।


2

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

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


2

मुझे लगता है कि मैं यहाँ उल्लेख नहीं देखा है refactoring के बारे में कुछ विश्वास करने के लिए आया हूँ, मुझे पता है कि यहाँ पहले से ही बहुत सारे उत्तर हैं, लेकिन मुझे लगता है कि यह नया है।

मैं एक निर्मम प्रतिशोधक और DRY में एक मजबूत विश्वासी रहा हूँ जब से कि शर्तें उठीं। ज्यादातर ऐसा इसलिए है क्योंकि मुझे अपने सिर में एक बड़ा कोडबेस रखने में परेशानी होती है और आंशिक रूप से क्योंकि मुझे DRY कोडिंग में मजा आता है और मुझे C & P कोडिंग के बारे में कुछ भी पसंद नहीं है, वास्तव में यह मेरे लिए दर्दनाक और बहुत धीमा है।

बात यह है, डीआरवाई पर जोर देते हुए मुझे कुछ तकनीकों में बहुत अभ्यास किया है जो कि मैं शायद ही कभी दूसरों का उपयोग करता हूं। बहुत सारे लोग जोर देते हैं कि जावा को DRY बनाना मुश्किल या असंभव है, लेकिन वास्तव में वे सिर्फ कोशिश नहीं करते हैं।

एक उदाहरण बहुत पहले से जो आपके उदाहरण से मिलता-जुलता है। लोगों को लगता है कि जावा जीयूआई निर्माण कठिन है। बेशक यह है अगर आप इस तरह से कोड:

Menu m=new Menu("File");
MenuItem save=new MenuItem("Save")
save.addAction(saveAction); // I forget the syntax, but you get the idea
m.add(save);
MenuItem load=new MenuItem("Load")
load.addAction(loadAction)

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

आप स्पष्ट रूप से इस तरह कोड नहीं कर सकते हैं ताकि आपको वापस कदम रखने और समस्या को देखने की जरूरत है, वह दोहराया गया कोड वास्तव में क्या कर रहा है? यह कुछ तार और उनके रिश्ते (एक पेड़) को निर्दिष्ट कर रहा है और उस पेड़ की पत्तियों को क्रियाओं में शामिल कर रहा है। तो आप वास्तव में क्या कहना चाहते हैं:

class Menu {
    @MenuItem("File|Load")
    public void fileLoad(){...}
    @MenuItem("File|Save")
    public void fileSave(){...}
    @MenuItem("Edit|Copy")
    public void editCopy(){...}...

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

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

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

मुझे नहीं लगता कि मैं अपनी नौकरी का आनंद ले पाऊंगा अगर मैं डीआरवाई तकनीक और उपकरण बनाने का अभ्यास नहीं कर पाऊंगा। अगर मुझे भुगतान में कटौती करनी थी और कॉपी प्रोग्रामिंग नहीं करनी थी, तो मैं इसे ले लूंगा।

तो मेरे अंक हैं:

  • कॉपी और पेस्ट में अधिक समय लगता है जब तक आप यह नहीं जानते कि अच्छी तरह से रिफैक्टर कैसे करें।
  • आप इसे अच्छी तरह से करना सीखते हैं - DRY पर जोर देते हुए यहां तक ​​कि सबसे कठिन और तुच्छ मामलों में भी।
  • आप एक प्रोग्रामर हैं, अगर आपको अपने कोड DRY को बनाने के लिए एक छोटे से टूल की जरूरत है, तो इसका निर्माण करें।

1

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


1

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

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

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

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


1
भले ही किसी फ़ंक्शन में इसे लपेटने वाले कथनों में सबसे सरल हो, इसे अधिक पठनीय बनाना चाहिए। ऐसे समय होते हैं जब किसी फ़ंक्शन में इसे लपेटना ओवरकिल होता है, लेकिन यदि आप एक फ़ंक्शन नाम के साथ नहीं आ सकते हैं जो कि अधिक संक्षिप्त और स्पष्ट है कि कथन क्या कर रहे हैं, तो यह संभवतः एक बुरा संकेत है। फ़ंक्शंस का उपयोग करने के लिए आपकी नकारात्मकता वास्तव में एक बड़ा सौदा नहीं है। इनलाइनिंग के लिए नकारात्मक एक बहुत बड़ा सौदा है। Inlining पढ़ने के लिए कठिन, बनाए रखने के लिए कठिन और पुन: उपयोग करने के लिए कठिन बनाता है।
21:39

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

मैंने यह सुनिश्चित करने के 3 नकारात्मक उल्लेख किया है कि जहां मैं केवल यह दावा करता हूं कि "अलग होना चाहिए"। मैं केवल इतना कह रहा हूं कि यदि आप एक नाम के साथ नहीं आ सकते हैं तो शायद आपकी बहुत ज्यादा जरूरत है। इसके अलावा, मुझे लगता है कि आप एक बड़े बिंदु को याद कर रहे हैं यहां तक ​​कि एक बार उपयोग किए जाने वाले छोटे तरीकों के बारे में भी। अच्छी तरह से नामित तरीके मौजूद हैं, इसलिए आपको यह जानने की ज़रूरत नहीं है कि कोड क्या करने की कोशिश कर रहा है (आईडीई कूद की कोई आवश्यकता नहीं है)। उदाहरण के लिए यहां तक ​​कि `अगर (दिन == 0 || दिन == 6)` बनाम का सरल कथन (यदि) (वीकेंड (दिन)) `पढ़ने और मानसिक रूप से मानचित्र को आसान बनाता है। अब अगर आपको उस कथन को दोहराने की आवश्यकता है, तो यह isWeekendदिमाग नहीं है।
22

@pllee आप दावा करते हैं कि यह "शायद एक बुरा संकेत है" यदि आपको लगभग हर दोहराया कोड टुकड़ा के लिए एक छोटा, स्पष्ट नाम नहीं मिल सकता है, लेकिन यह विश्वास की बात प्रतीत होती है - आप कोई सहायक तर्क नहीं देते हैं (एक सामान्य बनाने के लिए मामला, आपको उदाहरणों की तुलना में अधिक आवश्यकता है।) वीकेंड का एक सार्थक नाम है, इसलिए मेरे मानदंडों को विफल करने का एकमात्र तरीका यह है कि अगर यह न तो बहुत छोटा है और न ही इसके कार्यान्वयन की तुलना में काफी स्पष्ट है। यह तर्क देकर कि आपको लगता है कि यह उत्तरार्द्ध है, आप दावा कर रहे हैं कि यह मेरी स्थिति (FWIW) के लिए एक काउंटर-उदाहरण नहीं है, मैंने स्वयं का उपयोग किया है।)
sdenham

मैंने एक उदाहरण दिया जहां एक भी लाइन स्टेटमेंट अधिक पठनीय हो सकता है और मैंने इनलाइनिंग कोड के नकारात्मक दिए। यह मेरी विनम्र राय है और सभी मैं कह रहा हूं और नहीं मैं "निहत्थे पद्धति" के खिलाफ या बहस नहीं कर रहा हूं। मुझे वास्तव में यकीन नहीं है कि इस बारे में इतना भ्रमित क्या है या आपको क्यों लगता है कि मुझे अपनी राय के लिए "सैद्धांतिक प्रमाण" की आवश्यकता है। मैंने बेहतर पठनीयता की जांच की। रखरखाव कठिन है क्योंकि यदि कोड हंक बदल जाता है तो उसे एन संख्या के स्पॉट (डीआरवाई के बारे में पढ़ें) की आवश्यकता होती है। यह स्पष्ट रूप से पुन: उपयोग करने के लिए कठिन है जब तक आपको लगता है कि कॉपी पेस्ट नहीं है यदि कोड का पुन: उपयोग करने का एक व्यावहारिक तरीका है।
बजे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.