कोड के अंदर चर उपयोग को सामान्य करें


11

मैं यह जानना चाहूंगा कि क्या चर को सामान्य बनाना एक अच्छा अभ्यास है (सभी मूल्यों को संग्रहीत करने के लिए एकल चर का उपयोग करें)।
सरल उदाहरण पर विचार करें

 Strings querycre,queryins,queryup,querydel; 
    querycre = 'Create table XYZ ...';
    execute querycre ;
    queryins = 'Insert into XYZ ...';
    execute queryins ;
    queryup  = 'Update  XYZ set ...';
    execute queryup;
    querydel = 'Delete from XYZ ...';
    execute querydel ;

तथा

 Strings query; 
    query= 'Create table XYZ ... ';
    execute query ;
    query= 'Insert into XYZ ...';
    execute query ;
    query= 'Update  XYZ set ...';
    execute query ;
    query= 'Delete from XYZ ...';
    execute query ;

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

इसके अलावा बहुत सारे चर मेरे प्रदर्शन में बाधा डालते हैं?

पुनश्च: कृपया जवाब न दें कोड उदाहरण में यह सिर्फ यह बताने के लिए था कि मैं वास्तव में क्या मतलब है।


बेशक आप उसी चर का पुन: उपयोग करते हैं ... क्योंकि आपने इसे किसी फ़ंक्शन में परिभाषित किया है। यही कार्य हैं।
zzzzBov

जवाबों:


26

अपने आप से यह सवाल पूछना बहुत मजबूत गंध है कि आप DRY (खुद को दोहराएं नहीं) का पालन नहीं कर रहे हैं। मान लीजिए कि आपके पास यह है, एक काल्पनिक घुंघराले भाषा में:

function doFoo() {
    query = "SELECT a, b, c FROM foobar WHERE baz = 23";
    result = runQuery(query);
    print(result);

    query = "SELECT foo, bar FROM quux WHERE x IS NULL";
    result = runQuery(query);
    print(result);

    query = "SELECT a.foo, b.bar FROM quux a INNER JOIN quuux b ON b.quux_id = a.id ORDER BY date_added LIMIT 10";
    result = runQuery(query);
    print(result);
}

उस में रिफैक्टर:

function runAndPrint(query) {
    result = runQuery(query);
    print(result);
}

function doFoo() {
    runAndPrint("SELECT a, b, c FROM foobar WHERE baz = 23");
    runAndPrint("SELECT foo, bar FROM quux WHERE x IS NULL");
    runAndPrint("SELECT a.foo, b.bar FROM quux a INNER JOIN quuux b ON b.quux_id = a.id ORDER BY date_added LIMIT 10");
}

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


2
मुझे सिर्फ DRY सिद्धांत पसंद है :)
Artjom

1
@tdammers किसी फ़ंक्शन के अंदर कोड की सिर्फ 2 पंक्तियाँ रखना अच्छा है; विचार करें कि क्या मेरे पास यह फ़ंक्शन doFoo है () {प्रिंट (runQuery ("Selct a, b, c from XYZ");};}
शिरीषन

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

3
और कोड की सिर्फ दो पंक्तियों के साथ कार्य पूरी तरह से ठीक हैं: यदि दो पंक्तियाँ एक तार्किक इकाई बनाती हैं, तो दो पंक्तियाँ हैं। मैंने बहुत सारे वन-लाइनर फ़ंक्शंस लिखे हैं, बस कुछ जानकारी को अलग-थलग और एक जगह रखने के लिए।
तदमर्स

1
@JamesAnderson: यह कुछ हद तक वंचित उदाहरण है, लेकिन यह एक बिंदु को चित्रित करने का कार्य करता है। आपके पास कोड की कितनी पंक्तियाँ हैं, इसके बारे में नहीं है। यह कितनी बार आप एक ही तथ्य बताते हैं। DRY के बारे में यही है, साथ ही सत्य सिद्धांत के एकल स्रोत, तू नहीं कॉपी-पेस्ट नियम, आदि के बारे में है
tdammers

14

आम तौर पर, यह एक बुरा अभ्यास है।

एक चर का पुन: उपयोग इस तरह से कोड बना सकता है जो एक समझ को पढ़ने के लिए भ्रमित कर रहा है।

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

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

आपने जो उदाहरण दिए हैं, वे स्वयं को कार्यों में संलग्न होने के लिए उधार देते हैं, जहां आप क्वेरी में पास होंगे और इसे निष्पादित करेंगे।


सिस्टम के प्रदर्शन के बारे में क्या इससे प्रभावित होता है?
शिरीष

@ शिरीष 11 - यह हो सकता है। संकलक, भाषा, पर्यावरण और अन्य चर पर निर्भर करता है।
ऊद

आमतौर पर, कंपाइलर इसके अनुकूलन में अच्छे होते हैं। हालांकि, यह हमेशा संकलक / प्लेटफॉर्म / विशिष्ट मामले / कॉन्फ़िगरेशन पर निर्भर करता है।
deadalnix

7

स्व-प्रलेखित कोड पढ़ने और बनाए रखने में आसान है

कम से कम कम से कम के सिद्धांत का पालन ​​करें और कोड के रूप में प्रलेखन के रूप में : एक लक्ष्य के लिए एक चर का उपयोग करें, दोनों को समझने के लिए अपने उपयोग को आसान बनाने के लिए और स्पष्टीकरण के बिना पढ़ने के लिए आसान कोड।

सही ढंग से संरचित कोड आसान (इस प्रकार सस्ता) से (रे) का उपयोग है

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

इस तरह, आप प्रभावी ढंग से करेंगे:

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

उदाहरण:

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

आपका उदाहरण 1:

Strings querycre,queryins,queryup,querydel; 
    querycre = 'Create table XYZ ...';
    execute querycre ;
    queryins = 'Insert into XYZ ...';
    execute queryins ;
    queryup  = 'Update  XYZ set ...';
    execute queryup;
    querydel = 'Delete from XYZ ...';
    execute querydel ;

आपका उदाहरण 2:

 Strings query; 
    query= 'Create table XYZ ...';
    execute query ;
    query= 'Insert into XYZ ...';
    execute query ;
    query= 'Update  XYZ set ...';
    execute query ;
    query= 'Delete from XYZ ...';
    execute query ;

उदाहरण 3 (खंडित छद्म कोड):

def executeQuery(query, parameters...)
    statement = prepareStatement(query, parameters);
    execute statement;
end

// call point:
executeQuery('Create table XYZ ... ');
executeQuery('Insert into XYZ ...');
executeQuery('Update  XYZ set ...');
executeQuery('Delete from XYZ ...');

लाभ नियमित पुन: उपयोग के साथ दिखाता है।

व्यक्तिगत किस्सा

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

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

इसमें मेरे लिए क्या है?

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

विस्तार से, यह निम्न की ओर जाता है:

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

मैं यह नहीं कह रहा हूँ कि यहाँ परस्पर स्थिति का कोई लाभ नहीं है, मैं सिर्फ यह इंगित कर रहा हूँ कि आदत आप पर कैसे बढ़ सकती है और यह कोड पठनीयता को कैसे प्रभावित करता है।


2

कोड डिज़ाइन के संदर्भ में

सामान्य तौर पर, विभिन्न मूल्यों को संग्रहीत करने के लिए चर का पुन: उपयोग करना ठीक है - आखिरकार, उन्हें चर कहा जाता है, क्योंकि उनमें संग्रहीत मूल्य भिन्न होता है - जब तक कि मूल्य न केवल एक ही प्रकार का होता है, बल्कि एक ही चीज का अर्थ भी होता है । उदाहरण के लिए currentQueryयहाँ चर का पुन: उपयोग करना ठीक है:

for currentQuery in queries:
    execute query;

स्वाभाविक रूप से वहाँ एक पाश है ताकि आप है एक चर का पुन: उपयोग करने के लिए है, लेकिन यह ठीक हो गया होता, भले ही एक पाश नहीं था। यदि मान का मतलब एक ही बात नहीं है, तो एक अलग चर का उपयोग करें।

विशेष रूप से, हालांकि, आप जिस कोड का वर्णन कर रहे हैं वह बहुत अच्छा नहीं लगता है - यह खुद को दोहराता है । लूप या हेल्पर मेथड कॉल (या दोनों) का उपयोग करना बहुत बेहतर है। व्यक्तिगत रूप से मैंने बहुत कम ही उत्पादन कोड देखा है जो आपके 1 या 2 संस्करणों की तरह दिखता है, लेकिन मेरे पास मौजूद मामलों में, मुझे लगता है कि दूसरा संस्करण (चर पुन: उपयोग) अधिक सामान्य था।

प्रदर्शन के संदर्भ में

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

उदाहरण के लिए, gcc -O2सटीक एक ही बाइनरी उत्पन्न करता है, और एकमात्र प्रदर्शन अंतर जो मुझे पता है कि संकलन के दौरान प्रतीक तालिका का आकार है - पूरी तरह से नगण्य जब तक आप 60 के दशक में वापस नहीं जाते।

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


0

मुझे लगता है कि चर का पुन: उपयोग ज्यादातर समय ठीक है।

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


-1

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


मैंने सिर्फ एक सरल उदाहरण प्रदान किया है ताकि पाठकों को यह समझने में आसानी हो कि मैं क्या चाहता हूं। मेरा कोड इससे कहीं अधिक जटिल है।
शिरीष

-2

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

{
    String query = 'Create table XYZ ...';
    execute query;
}
{
    String query = 'Insert table XYZ ...';
    execute query;
}
And so on...

(इस बिंदु पर, मैं tdammers समाधान पर विचार कर सकता हूं ।)

पहले उदाहरण के साथ समस्या यह है कि querycreपूरे ब्लॉक के लिए गुंजाइश है, जो व्यापक हो सकती है। यह कोड पढ़ने वाले किसी व्यक्ति को भ्रमित कर सकता है। यह ऑप्टिमाइज़र को भी भ्रमित कर सकता है, जो अनावश्यक मेमोरी राइट में छोड़ सकता है इसलिए querycreबाद में जरूरत पड़ने पर उपलब्ध है (जो कि ऐसा नहीं है)। सभी ब्रेसिज़ के साथ, queryकेवल एक रजिस्टर में संग्रहीत किया जाता है, यदि वह।

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


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

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

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