क्या केवल सामान्य कोड को केंद्रीकृत करने के लिए कार्यों का उपयोग करना अच्छा है?


20

मैं इस समस्या को बहुत बढ़ाता हूं। उदाहरण के लिए, मैं वर्तमान में एक रीड फंक्शन और एक राइट फंक्शन लिखता हूं, और वे दोनों चेक करते हैं कि bufक्या NULL पॉइंटर है और modeवेरिएबल कुछ सीमाओं के भीतर है।

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

तो, आप इस तरह से कुछ के लिए एक समारोह का उपयोग करना चाहिए? पक्ष और विपक्ष क्या होते हैं?


2
एकल पंक्ति सामान को एक अलग फ़ंक्शन में स्थानांतरित करने के लिए कई स्थानों पर उपयोग किए जाने से अधिक की आवश्यकता होती है।

1
बड़ा सवाल है। ऐसा कई बार हुआ है जब मैंने सोचा है।
rdasxy

जवाबों:


31

यह फ़ंक्शन का एक महान उपयोग है।

यह एक बहुत ही एनीमिक फंक्शन होगा (ज्यादा कुछ नहीं करता) ...

अच्छी बात है। कार्य केवल एक ही करना चाहिए।

बल्कि स्थानीयकृत ...

OO भाषा में, इसे निजी बनाएं।

(इसलिए सामान्य उद्देश्य नहीं)

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

और अपने दम पर अच्छी तरह से खड़ा नहीं होता है (यह पता नहीं लगा सकता है कि आपको इसकी आवश्यकता तब तक है जब तक आप यह नहीं देखते कि यह कहाँ उपयोग किया जाता है)।

इसके लिए एक अच्छा नाम है, और यह अपने आप ठीक है। "ValidateFileParameters" या कुछ और। अब अपने आप ठीक है।


6
अच्छी तरह से माल अंक। जब आप एक स्थान पर ठीक कर सकते हैं तो मैं आपके पूरे कोड बेस में एक डुप्लिकेटेड बग के शिकार से आपको रोकूंगा। कोड दोहराव बहुत तेजी से एक रखरखाव नरक का कारण बन सकता है।
deadalnix

2
@ डेडलोनिक्स: अच्छी बात है। जैसा कि मैं लिख रहा था मुझे एहसास हुआ कि मेरे अंक एक सकल अति-सरलीकरण थे। लेखन और आसान डिबगिंग निश्चित रूप से कार्यों में चीजों को विभाजित करने का एक लाभ है (जैसा कि अलग-अलग कार्यों की इकाई परीक्षण की क्षमता है)।
क्रामि ने मोनिका को

11

यह पूरी तरह से एक समारोह होना चाहिए।

if (isBufferValid(buffer)) {
    // ...
}

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

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

मुझे आपसे एक बेहतर सवाल पूछना है। कैसे की जाती है यह नहीं कर रही एक अच्छा अभ्यास?

सही चीज़ करना। :)


4
अगर BufferValid बस है, return buffer != null;तो मुझे लगता है कि आप वहां पठनीयता पर चोट कर रहे हैं।
पीडीआर

5
@pdr: उस सरल स्थिति में यह केवल पठनीयता को चोट पहुँचाता है यदि आपके पास नियंत्रण फ्रीक की मानसिकता है और वास्तव में, वास्तव में, यह जानना चाहता है कि यदि बफ़र मान्य है तो कोड कैसे चेक करता है। तो यह उन सरल मामलों में व्यक्तिपरक है।
स्पूइक

4
@ मुझे पता नहीं है कि यह किसी भी मानक द्वारा पठनीयता को नुकसान पहुंचाता है। आप अन्य डेवलपर्स को इस बात की देखभाल करने से छूट दे रहे हैं कि आप कुछ कैसे कर रहे हैं, और आप क्या कर रहे हैं , इस पर ध्यान केंद्रित कर रहे हैं। isBufferValidनिश्चित रूप से (मेरी पुस्तक में) से अधिक पठनीय है buffer != null, क्योंकि यह उद्देश्य को अधिक स्पष्ट रूप से बताता है। और फिर, इसका उल्लेख नहीं करना आपको यहां तक ​​दोहराव से बचाता है। आपको और क्या चाहिए?
यम मारकोविच

5

IMO, कोड स्निपेट को अपने स्वयं के कार्यों में ले जाने के लायक है जब भी यह कोड को अधिक पठनीय बनाता है , भले ही फ़ंक्शन बहुत कम हो या केवल एक बार उपयोग किया जाएगा।

सामान्य ज्ञान द्वारा निर्धारित पाठ्यक्रम सीमाएँ हैं। आप उदाहरण के लिए WriteToConsole(text)शरीर के साथ विधि नहीं चाहते हैं Console.WriteLine(text)। लेकिन पठनीयता के पक्ष में गलती करना एक अच्छा अभ्यास है।


2

आमतौर पर कोड में दोहराव को हटाने के लिए कार्यों का उपयोग करना एक अच्छा विचार है।

हालाँकि इसे बहुत दूर तक ले जाया जा सकता है। यह एक निर्णय कॉल है।

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

if (buf==null) throw new BufferException("Null read buffer!");

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

checkForNullBuffer(buf, "Null read buffer!");

इसके अतिरिक्त, फ़ंक्शन में गोता लगाने के लिए यह देखने के लिए कि यह क्या कर रहा है जब डिबगिंग का अर्थ है कि फ़ंक्शन कॉल उपयोगकर्ता के लिए "पारदर्शी" कम है, और इसलिए इसे कम पठनीय / रखरखाव योग्य माना जा सकता है।


तर्क से, आपकी छूट दोहराव की वास्तविक आवश्यकता की तुलना में भाषा में अनुबंध समर्थन की कमी के बारे में अधिक कहती है। लेकिन वैसे भी अच्छे अंक।
deadalnix

1
आप जिस तरह से मैं इसे देखने के बिंदु से चूक गए। नहीं पर कदम या तर्क हर बार जब आप डिबग पर विचार करने के लिए हो रही है क्या मैं कर रहा हूँ की तलाश में। यदि मैं जानना चाहता हूं कि यह कैसे किया जाता है, तो मैं इसे एक बार जांचता हूं। यह हर बार करने के बाद बस मूर्खतापूर्ण है।
यम मार्कोविच

यदि त्रुटि संदेश ("नल रीड बफर") दोहराया जाता है, तो दोहराव को निश्चित रूप से समाप्त किया जाना चाहिए।
केविन क्लाइन

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

-1 Preconditions.checkNotNull एक अच्छा अभ्यास है, बुरा नहीं है। हालांकि स्ट्रिंग संदेश को शामिल करने की आवश्यकता नहीं है। google-collections.googlecode.com/svn/trunk/javadoc/com/google/...
ripper234

2

कोड को केंद्रीकृत करना आमतौर पर हमेशा एक अच्छा विचार होता है। हमें यथासंभव कोड का फिर से उपयोग करना चाहिए।

हालांकि, यह ध्यान रखना महत्वपूर्ण है कि यह कैसे करना है। उदाहरण के लिए, जब आपके पास एक कोड होता है जो compute_prime_number () या check_if_packet_is_bad () अच्छा होता है। संभावना है कि कार्यक्षमता का एल्गोरिथ्म स्वयं विकसित होगा जो लाभान्वित होगा।

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

यहां कुछ सवाल हैं जिन्हें आपको पूछने से पहले पूछना चाहिए

  1. क्या फ़ंक्शन आप अपने स्वयं के अंतर्निहित अर्थ का निर्माण कर रहे हैं या यह सिर्फ लाइनों का एक गुच्छा है?

  2. किन अन्य संदर्भों में समान कार्यों के उपयोग की आवश्यकता होगी? क्या यह संभावना है कि आपको इसका उपयोग करने से पहले एपीआई को थोड़ा सामान्य करने की आवश्यकता हो सकती है?

  3. अपवादों को फेंकने पर (विभिन्न भागों में) अनुप्रयोगों की क्या उम्मीद होगी?

  4. यह देखने के लिए कि क्या कार्य विकसित होने वाले हैं?

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

अनिवार्य रूप से, सवाल यह है कि, "क्या यह नया कार्य वास्तव में पुन: उपयोग के योग्य है या यह सिर्फ एक कॉपी-पेस्ट है ?" अगर पहले है, तो जाना अच्छा है।


1
ठीक है, अगर डुप्लिकेट कोड का अपना अर्थ नहीं है, तो आपका कोड आपको बता रहा है कि उसे रिफैक्टिंग की आवश्यकता है। क्योंकि जिन स्थानों पर दोहराव होता है, उनके अपने अर्थ भी नहीं होते हैं।
डेडलिंक

1

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

कोड डुप्लिकेट क्या है?

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

नीचे दिए गए उदाहरण पर विचार करें:

if(user.getPrileges().contains("admin")) {
    // Do something
}

हो जाता है

if(user.isAdmin()) {
    // Do something
}

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


1
Btw उदाहरण डेमेटर के कानून को दर्शाता है।
MaR

1

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


0

यदि आप इसे डुप्लिकेट देखते हैं, तो आपको इसे केंद्रीकृत करने का एक तरीका खोजना चाहिए।

फ़ंक्शंस एक अच्छा तरीका है (शायद सबसे अच्छा नहीं है लेकिन यह भाषा पर निर्भर करता है) भले ही फ़ंक्शन अनीमिक हो, जैसा कि आप कहते हैं कि इसका मतलब यह नहीं है कि यह उस तरह से रहेगा।

क्या होगा अगर आपको किसी और चीज़ के लिए भी जाँच करनी है?

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


... दूसरी ओर, क्या होगा अगर वहाँ एक बहुत ही उच्च संभावना है कि आप इसमें कुछ नहीं जोड़ेंगे। क्या आपका सुझाव अभी भी उस मामले में कार्रवाई का सबसे अच्छा पाठ्यक्रम है?
एप्सिलॉनवेक्टर

1
@ EpsilonVector मेरे अंगूठे का नियम है कि अगर मुझे इसे एक बार बदलना है तो मैं इसे भी ठीक कर सकता हूं। तो, आपके मामले में मैं इसे छोड़ दूंगा और अगर मुझे इसे बदलना पड़ा, तो यह एक समारोह बन जाएगा।
थानोस पापनाथनसॉ

0

यदि निम्न स्थितियाँ मिलें तो यह लगभग हमेशा अच्छा होता है:

  • पठनीयता में सुधार
  • सीमित दायरे में उपयोग किया जाता है

बड़े दायरे में आपको दोहराव बनाम निर्भरता व्यापार-नापसंद को ध्यान से तौलना चाहिए। गुंजाइश सीमित करने की तकनीक के उदाहरण: निजी खंडों या मॉड्यूल में उन्हें सार्वजनिक किए बिना छिपाना।

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