यदि हम कर सकते हैं तो क्या हमें स्थानीय चरों को समाप्त करना चाहिए?


95

उदाहरण के लिए, एंड्रॉइड पर सीपीयू रखने के लिए, मैं इस तरह कोड का उपयोग कर सकता हूं:

PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "abc");
wakeLock.acquire();

लेकिन मुझे लगता है कि स्थानीय चर powerManagerऔर wakeLockसमाप्त किया जा सकता है:

((PowerManager)getSystemService(POWER_SERVICE))
    .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag")
    .acquire();

इसी तरह का दृश्य आईओएस अलर्ट दृश्य में दिखाई देता है, जैसे: से

UIAlertView *alert = [[UIAlertView alloc]
    initWithTitle:@"my title"
    message:@"my message"
    delegate:nil
    cancelButtonTitle:@"ok"
    otherButtonTitles:nil];
[alert show];

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    [alertView release];
}

सेवा:

[[[UIAlertView alloc]
    initWithTitle:@"my title"
    message:@"my message"
    delegate:nil
    cancelButtonTitle:@"ok"
    otherButtonTitles:nil] show];

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    [alertView release];
}

क्या स्थानीय वेरिएबल को खत्म करना एक अच्छा अभ्यास है अगर इसे सिर्फ एक बार स्कोप में इस्तेमाल किया जाए?


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

75
यह कोड w / डीबगर के माध्यम से भी कदम रखना अधिक कठिन बनाता है। और आपको यह भी सुनिश्चित करना होगा (भाषा के आधार पर) पहली अभिव्यक्ति एक पूर्ण या त्रुटि नहीं है।
ग्रैंडमास्टरबी

78
नहीं, यह नहीं है। वास्तव में, विधि कॉलों की श्रृंखलाओं को तोड़ने के लिए स्थानीय चर पेश करना अच्छा अभ्यास है । उत्पन्न मशीन कोड समान होने की संभावना है, और स्रोत कोड लगभग पठनीय होने की गारंटी है, इसलिए बेहतर है।
किलन फ़ॉथ

48
उसकी कोशिश करो। अब डिबगर प्लग करें और पावर मैनजर या वेकॉकॉक की स्थिति को देखने का प्रयास करें। अपनी गलती का एहसास। मैं यही सोचता था ("इन सभी स्थानीय लोगों के साथ क्या है?") जब तक मुझे अपना अधिकांश समय जांच कोड में बिताना नहीं पड़ता।
फरिंदेल

42
यहां तक ​​कि आपके उदाहरण में, आपके "समाप्त" संस्करण में एक स्क्रॉल पट्टी है और पूरी तरह से मेरी स्क्रीन पर फिट नहीं होती है, जिससे इसे पढ़ना बहुत कठिन हो जाता है।
एरिक

जवाबों:


235

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

और अगर आपको लगता है कि आप स्थानीय चर से छुटकारा पाकर किसी भी चीज का अनुकूलन कर रहे हैं, तो आप नहीं हैं। एक आधुनिक संकलक powerManagerएक रजिस्टर 1 में रखा जाएगा , चाहे एक स्थानीय चर का उपयोग किया जाए या नहीं, newWakeLockविधि को कॉल करने के लिए। उसी के लिए सच है wakeLock। तो आप किसी भी स्थिति में समान संकलित कोड के साथ अंत करते हैं।

1 यदि आपके पास घोषणा और स्थानीय चर के उपयोग के बीच बहुत अधिक हस्तक्षेप कोड है, तो यह स्टैक पर जा सकता है, लेकिन यह एक छोटा विवरण है।


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

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

15
@Walfrat स्थानीय चर कई बार आरंभिक हो रहे हैं? आउच। किसी ने भी स्थानीय लोगों का पुन: उपयोग करने का सुझाव नहीं दिया :)
लूआन

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

4
प्रश्न: यदि हम कर सकते हैं तो क्या हमें स्थानीय चरों को समाप्त करना चाहिए? उ: नहीं
सिमोन

94

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

Debuggability

अक्सर, डेवलपर कोड लिखने की तुलना में अधिक समय और प्रयास डिबगिंग में बिताते हैं।

स्थानीय चर के साथ , आप कर सकते हैं:

  • लाइन पर ब्रेकपॉइंट जहां इसे सौंपा गया है (सभी अन्य ब्रेकपॉइंट सजावट के साथ, जैसे सशर्त ब्रेकपॉइंटिंग, आदि ...)

  • स्थानीय चर का निरीक्षण / घड़ी / प्रिंट / परिवर्तन-मूल्य

  • कैच के कारण पैदा होने वाले मुद्दे

  • सुव्यवस्थित स्टैक निशान (लाइन XYZ में 10 के बजाय एक ऑपरेशन है)

स्थानीय चर के बिना, आपके डिबगर के आधार पर उपरोक्त सभी कार्य या तो बहुत कठिन हैं, अत्यंत कठिन हैं, या बिल्कुल असंभव हैं।

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


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

3
कोड के माध्यम से कदम रखना भी बहुत कठिन है। यदि कॉल () -> कॉल () -> कॉल () -> कॉल () है, तो तीसरी विधि कॉल में कदम रखना कठिन काम है। बहुत आसान है अगर चार स्थानीय चर हैं
gnasher729

3
@FrankPuffer - हमें वास्तविक दुनिया से निपटना होगा। जहां डिबगर्स वह नहीं करते हैं जो आप प्रस्तावित करते हैं।
डीवीके

2
@ डीवीडीके: वास्तव में मेरे विचार से अधिक डिबगर्स हैं जो आपको किसी भी अभिव्यक्ति का निरीक्षण करने या देखने की अनुमति देते हैं। MS Visual Studio (संस्करण 2013 से) में C ++ और C # के लिए यह सुविधा है। ग्रहण जावा के लिए है। एक अन्य टिप्पणी में, Faerindel ने JS के लिए IE11 का उल्लेख किया।
फ्रैंक पफर

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

47

केवल अगर यह कोड को समझने में आसान बनाता है। आपके उदाहरणों में, मुझे लगता है कि इसे पढ़ना कठिन है।

संकलित कोड में चर को खत्म करना किसी भी सम्मानजनक संकलक के लिए एक तुच्छ ऑपरेशन है। आप सत्यापित करने के लिए आउटपुट का स्वयं निरीक्षण कर सकते हैं।


1
इसका वैसा ही है जैसा स्टाइल के साथ वैरिएबल का इस्तेमाल होता है। प्रश्न को अब संपादित कर दिया गया है।
जोड्रेल

29

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

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

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


मुझे लगता है कि स्टाइल और कुछ के रूप में व्हॉट्सएप के उपयोग के साथ बहुत कुछ करना है। प्रश्न संपादित किया गया है।
जोड्रेल

15

शायद।

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

कोड संपादक द्वारा प्रदान किया गया सिंटैक्स हाइलाइटिंग कुछ हद तक इस तरह की चिंताओं को कम कर सकता है।

मेरी नजर में, यह बेहतर समझौता है:

PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "abc").acquire();

इस प्रकार एक स्थानीय वैरिएबल को रखना और दूसरे को डिच करना। C # में मैं पहले लाइन पर var कीवर्ड का उपयोग करता हूँ क्योंकि टाइपकास्ट पहले से ही टाइप जानकारी प्रदान करता है।


13

यद्यपि मैं स्थानीय चर के पक्ष में उत्तर की वैधता को स्वीकार करता हूं, मैं शैतान के वकील की भूमिका निभाने जा रहा हूं और एक विरोधाभासी दृश्य प्रस्तुत कर रहा हूं।

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

आपके मामले में, मुख्य समस्या इंडेंटेशन है न कि वेरिएबल्स की अनुपस्थिति। आप निम्नानुसार कोड को प्रारूपित कर सकते हैं (और चाहिए):

((PowerManager)getSystemService(POWER_SERVICE))
        .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"MyWakelockTag")
        .acquire();

इसकी तुलना स्थानीय चर वाले संस्करण से करें:

PowerManager powerManager=(PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"abc");
wakeLock.acquire();

स्थानीय चर के साथ: नाम पाठक के लिए कुछ जानकारी जोड़ते हैं और प्रकार स्पष्ट रूप से निर्दिष्ट होते हैं, लेकिन वास्तविक विधि कॉल कम दिखाई देती हैं और (मेरी राय में) यह स्पष्ट रूप से नहीं पढ़ती है।

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

तीन और टिप्पणियाँ:

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

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

  3. डिबगिंग स्थानीय चर के साथ आसान हो सकती है यदि आपका डिबगर तरीकों से लौटाए गए मूल्यों को नहीं दिखाता है। लेकिन इसके लिए फिक्स डिबगर्स में कमियों को ठीक करना है, कोड को बदलना नहीं।


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

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

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

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

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

6

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

इन बाद के रिफ्लेक्टरिंग के लिए प्रेरणाओं पर, फाउलर लिखते हैं :

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

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

FWIW मैंने व्यक्तिगत रूप से फाउलर की पुस्तक "रिफैक्टिंग" को दस वर्षों तक पढ़ने से परहेज किया क्योंकि मैंने कल्पना की थी कि ऐसे अपेक्षाकृत सीधे विषयों पर कहने के लिए बहुत कुछ नहीं था। मैं पूरी तरह से गलत था। जब मैंने अंततः इसे पढ़ा, तो इसने मेरी दैनिक कोडिंग प्रथाओं को बदल दिया, बेहतर के लिए बहुत कुछ।


1
बहुत बढ़िया जवाब। सबसे अच्छा कोड जो मैंने लिखा है (और दूसरों से देखा है) अक्सर बहुत सारे छोटे (2, 3 लाइनें) तरीके होते थे जो ऐसे अस्थायी चर की जगह ले सकते थे। संबंधित यह विवादास्पद है कि निजी तरीकों से बदबू आती है .... अच्छी तरह से सोचा गया है और मैंने अक्सर इसे सच पाया है।
Stijn de Witt

इस सवाल में टेम्प्स पहले से ही फ़ंक्शन का उल्लेख करते हैं, इसलिए यह उत्तर ओपी प्रश्न के लिए अप्रासंगिक है।
user949300

@ user949300 मुझे नहीं लगता कि यह अप्रासंगिक है। हां, ओपी के विशिष्ट उदाहरण में टेम्प्स फ़ंक्शन या विधियों से वापसी मान हैं। लेकिन ओपी बहुत स्पष्ट है कि सिर्फ एक उदाहरण परिदृश्य है। वास्तविक प्रश्न बहुत अधिक सामान्य है "क्या हमें अस्थायी चर को समाप्त करना चाहिए जब हम कर सकते हैं?"
जोनाथन हार्टले

1
ठीक है, मैं बेच दिया गया हूं, ** अपना वोट बदलने के लिए ** की कोशिश की। लेकिन अक्सर जब मैं ओपी प्रश्न के सीमित दायरे से आगे निकल जाता हूं तो मुझे घिन आती है। एसओ चंचल हो सकता है ... :-)। Er, जब तक आप संपादित नहीं करते, तब तक मेरा वोट नहीं बदल सकता ...
user949300

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

3

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

acquireWakeLock(POWER_SERVICE, PARTIAL, "abc");

तब मैं कहूंगा कि यह शायद एक अच्छा विचार होगा। शायद आप इसे कुछ इसी तरह उबालने के लिए सहायक तरीके पेश कर सकते हैं; यदि इस तरह का कोड कई बार दिखाई देता है तो यह अच्छी तरह से सार्थक हो सकता है।


2

आइए यहां कानून के कानून पर विचार करें। LoD पर विकिपीडिया लेख में निम्नलिखित कहा गया है:

कार्यों के लिए कानून के कानून की आवश्यकता है कि एक वस्तु ओ की एक विधि एम केवल निम्नलिखित प्रकार की वस्तुओं के तरीकों को लागू कर सकती है: 2]

  1. ओ ही है
  2. मीटर के मापदंडों
  3. किसी भी वस्तु को बनाया / मी के भीतर त्वरित
  4. ओ के प्रत्यक्ष घटक वस्तुओं
  5. एक वैश्विक चर, ओ के द्वारा सुलभ, मी के दायरे में

इस कानून का पालन करने के परिणामों में से एक यह है कि आपको एक लंबी डॉटेड-स्ट्रिंग में अन्य तरीकों से लौटाए गए ऑब्जेक्ट के तरीकों को लागू करने से बचना चाहिए, जैसा कि ऊपर दिए गए दूसरे उदाहरण में दिखाया गया है:

((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"MyWakelockTag").acquire();

यह पता लगाना वास्तव में मुश्किल है कि यह क्या कर रहा है। इसे समझने के लिए आपको यह समझना होगा कि प्रत्येक प्रक्रिया क्या करती है, और फिर यह समझने के लिए कि किस फ़ंक्शन को किस ऑब्जेक्ट पर बुलाया जा रहा है। पहला कोड ब्लॉक

PowerManager powerManager=(PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock=powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"abc");
wakeLock.acquire();

स्पष्ट रूप से दिखाता है कि आप क्या करने की कोशिश कर रहे हैं - आप पावर मैनजर ऑब्जेक्ट प्राप्त कर रहे हैं, पावरमैनेजर से एक वेकॉक ऑब्जेक्ट प्राप्त कर रहे हैं, फिर वेकॉक प्राप्त कर रहे हैं। उपरोक्त नियम LoD के # 3 नियम - आप इन वस्तुओं को अपने कोड के भीतर इंस्टेंट कर रहे हैं, और इस प्रकार उनका उपयोग कर सकते हैं कि आपको जो आवश्यक है वह किया जाए।

शायद सोचने का एक और तरीका यह है कि यह याद रखें कि सॉफ्टवेयर बनाते समय आपको स्पष्टता के लिए लिखना चाहिए, न कि संक्षिप्तता के लिए। सभी सॉफ्टवेयर विकास का 90% रखरखाव है। कभी भी ऐसा कोड न लिखें जिसे आप बनाए रखने में खुश न हों।

शुभकामनाएँ।


3
मुझे इस बात में दिलचस्पी होगी कि इस उत्तर में द्रव सिंटैक्स कैसे फिट होता है। सही स्वरूपण के साथ, द्रव सिंटैक्स अत्यधिक पठनीय है।
गुसादोर

12
यही नहीं "लॉ ऑफ़ डेमेटर" का अर्थ है। लॉ ऑफ़ डेमेटर एक गिनती की कवायद नहीं है; इसका अनिवार्य रूप से अर्थ है "केवल अपने तात्कालिक दोस्तों से बात करना।"
रॉबर्ट हार्वे

5
इंटरमीडिएट चर के माध्यम से समान विधियों और सदस्यों तक पहुंचना अभी भी उतना ही गंभीर है जितना कि डेमेटर के कानून का उल्लंघन। आपने इसे ठीक नहीं किया है।
जोनाथन हार्टले

2
"लॉ ​​ऑफ़ डेमेटर" के संदर्भ में, दोनों संस्करण समान रूप से "खराब" हैं।
हल्क

@Gusdor ने सहमति व्यक्त की, यह प्रश्न उदाहरण में स्टाइल पर एक टिप्पणी है। प्रश्न को अब संपादित कर दिया गया है।
जोडरेल

2

ध्यान देने वाली बात यह है कि कोड को अक्सर "अलग-अलग" गहराई तक पढ़ा जाता है। यह कोड:

PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "abc");
wakeLock.acquire();

"स्किम" करना आसान है। यह 3 कथन है। पहले हम एक के साथ आते हैं PowerManager। फिर हम एक साथ आते हैं WakeLock। तब हम acquirewakeLock। मैं प्रत्येक पंक्ति की शुरुआत को देखकर वास्तव में आसानी से देख सकता हूं; सरल चर असाइनमेंट को आंशिक रूप से "Type varName = ..." के रूप में आंशिक रूप से पहचानना आसान है और "..." पर मानसिक रूप से स्किम करें। इसी तरह अंतिम कथन स्पष्ट रूप से असाइनमेंट का रूप नहीं है, लेकिन इसमें केवल दो नाम शामिल हैं, इसलिए "मुख्य जिस्ट" तुरंत स्पष्ट है। अक्सर यह सब मुझे जानना होगा कि क्या मैं जवाब देने की कोशिश कर रहा था "यह कोड क्या करता है?" उच्च स्तर पर।

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

((PowerManager)getSystemService(POWER_SERVICE))
    .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag")
    .acquire();

अब यह सब एक बयान है। शीर्ष स्तर की संरचना स्किम-रीड करने के लिए इतनी आसान नहीं है; ओपी के मूल संस्करण में, बिना किसी संरचना के लाइनब्रेक और इंडेंटेशन के, मुझे 3 चरणों के अनुक्रम में इसे डिकोड करने के लिए कोष्ठक को गिनना होगा। यदि कुछ मल्टी-पार्ट एक्सप्रेशंस मेथड कॉल की एक श्रृंखला के रूप में व्यवस्थित होने के बजाय एक-दूसरे के भीतर नेस्टेड हैं, तो यह अभी भी इसी तरह से बाहर आ सकता है, इसलिए मुझे यह भरोसा करने के बारे में सावधान रहना होगा कि बिना कोष्ठक की गिनती के। और अगर मैं इस सब के प्रकल्पित बिंदु के रूप में इंडेंटेशन पर भरोसा करता हूं और अंतिम बात के आगे स्किम करता .acquire()हूं , तो मुझे अपने आप से क्या कहना है?

हालांकि कभी-कभी, यह वही हो सकता है जो आप चाहते हैं। अगर मैं आपके परिवर्तन को आधे-अधूरे तरीके से लागू करूँ और लिखा:

WakeLock wakeLock =
     ((PowerManeger)getSystemService(POWER_SERVICE))
    .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLockTage");
wakeLock.acquire();

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

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


मेरे लिए, भले ही मुझे एपीआई का कोई ज्ञान नहीं है, यह बहुत स्पष्ट है कि कोड क्या करता है, चर के बिना भी। getSystemService(POWER_SERVICE)पावर मैनेजर हो जाता है। .newWakeLockएक जगा ताला मिलता है। .acquireइसे प्राप्त करता है। ठीक है, मैं सभी प्रकारों को नहीं जानता, लेकिन अगर मुझे आवश्यकता हो तो मैं आईडीई में पता लगा सकता हूं।
रागोम

यह आपके लिए स्पष्ट हो सकता है कि कोड क्या करना चाहिए , लेकिन आपके पास कोई सुराग नहीं है कि यह वास्तव में क्या करता है। अगर मैं एक बग की तलाश कर रहा हूं, तो मुझे पता है कि कुछ कोड कहीं ऐसा नहीं करता है जो उसे करना चाहिए, और मुझे यह पता लगाना होगा कि कौन सा कोड है।
gnasher729

@ gnasher729 हाँ। बग-शिकार एक उदाहरण था जो मैंने दिया था जब आपको सभी विवरणों को ध्यान से पढ़ने की आवश्यकता होगी। और एक चीज़ जो वास्तव में उस कोड को खोजने में मदद करती है जो ऐसा नहीं कर रहा है जो वह करने वाला है वह आसानी से देख सकता है कि मूल लेखक का इरादा क्या था।
बेन

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

2

यह अपने स्वयं के नाम के साथ एक एंटीपैटर्न भी है: ट्रेन व्रेक । प्रतिस्थापन से बचने के कई कारण पहले ही बताए जा चुके हैं:

  • पढ़ने में कठिन
  • डिबग करने के लिए कठिन (दोनों चर देखने और अपवाद स्थानों का पता लगाने के लिए)
  • कानून का उल्लंघन (LoD)

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

यह भी याद रखें कि वस्तुओं के संदर्भ वास्तव में सस्ते हैं।


एहम संशोधित कोडिंग विधि नहीं है? EDIT लिंक किए गए लेख को पढ़ें ताकि मुझे अब अंतर दिखाई दे। बहुत अच्छा लेख धन्यवाद!
Stijn de Witt

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

मुझे लगता है कि "ट्रेन मलबे" के विपरीत "लोकल लाइन" है। यह दो प्रमुख शहरों के बीच ट्रेन है जो हर देश के गांव में बस के बीच में रुकती है, जब कोई व्यक्ति उतरना या उतरना चाहता है, भले ही अधिकांश दिन कोई भी क्यों न हो।
rghome

1

कहा गया प्रश्न "क्या हम स्थानीय चर को समाप्त कर सकते हैं यदि हम कर सकते हैं"?

नहीं, आपको केवल इसलिए नहीं खत्म करना चाहिए कि आप कर सकते हैं।

आपको अपनी दुकान में कोडिंग दिशानिर्देशों का पालन करना चाहिए।

अधिकांश भाग के लिए स्थानीय चर कोड को पढ़ना और डीबग करना आसान बनाते हैं।

मुझे पसंद है कि आपने क्या किया PowerManager powerManager। मेरे लिए कक्षा का निचला मामला मतलब है कि यह सिर्फ एक समय का उपयोग है।

जब आपको यह नहीं करना चाहिए कि क्या चर महंगे संसाधनों पर पकड़ रखने वाला है। कई भाषाओं में एक स्थानीय चर के लिए वाक्यविन्यास होता है जिसे साफ / जारी करने की आवश्यकता होती है। C # में यह उपयोग कर रहा है।

using(SQLconnection conn = new SQLconnnection())
{
    using(SQLcommand cmd = SQLconnnection.CreateCommand())
    {
    }
}

यह वास्तव में स्थानीय चर से संबंधित नहीं है, लेकिन संसाधन सफाई के लिए है ... मैं सी # में अच्छी तरह से वाकिफ नहीं हूं, लेकिन मुझे आश्चर्य using(new SQLConnection()) { /* ... */ }होगा कि क्या कानूनी भी नहीं होगा (क्या यह उपयोगी होगा एक अलग मामला है :)।
स्टिजन डे विट

1

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

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

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


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

@ जिमीजैम: ने मेरे उत्तर में कुछ व्याख्या जोड़ दी है। लेकिन आपकी टिप्पणी का एक हिस्सा है जो मुझे समझ में नहीं आया: "स्थानीय चर का उपयोग पारस्परिक स्थिति से निपटने में मदद करता है"। क्या आप इसे समझा सकते हैं?
फ्रैंक पफ़र

1
उदाहरण के लिए, मान लें कि मुझे एक मान की जाँच करने की आवश्यकता है और यदि यह 10 से अधिक आग की चेतावनी है। मान लीजिए कि यह मान विधि से आता है getFoo()। यदि मैं एक स्थानीय घोषणा से बचता हूं, तो मैं if(getFoo() > 10) alert(getFoo());दो अलग-अलग कॉल पर अलग-अलग मान लौटा सकता हूं। मैं एक मान के साथ एक चेतावनी भेज सकता है जो 10 से कम या उसके बराबर है जो सबसे अच्छा भ्रमित है और एक दोष के रूप में मेरे पास वापस आ जाएगा। इस तरह की बात संगति के साथ अधिक महत्वपूर्ण हो जाती है। स्थानीय असाइनमेंट परमाणु है।
जिम्मीजैम

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

हाल ही में एक बात पर, स्पीकर ने तर्क दिया कि यह दिखाने का सबसे अच्छा तरीका है कि एक चर अंतिम है , छोटी विधियों को लिखना है जहां यह स्पष्ट है कि चर नहीं बदलता है । यदि finalएक विधि में एक स्थानीय चर पर जरूरत है, तो आपकी विधि बहुत लंबी है।
user949300
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.