लंबे समय से रीफैक्टरिंग: स्थानीय कार्यों का उपयोग करते हुए बनाम अलग-अलग तरीकों से छोड़ना


9

मान लीजिए कि मेरे पास इस तरह की लंबी विधि है:

public void SomeLongMethod()
{
    // Some task #1
    ...

    // Some task #2
    ...
}

इस विधि में कोई दोहराव वाले हिस्से नहीं हैं जिन्हें अलग विधि या स्थानीय फ़ंक्शन में ले जाना चाहिए।

कई लोग हैं (मेरे सहित) जो सोचते हैं कि लंबी विधियाँ कोड गंध हैं। इसके अलावा, मुझे #regionयहाँ उपयोग करने का विचार पसंद नहीं है और यह समझाने के लिए एक बहुत ही लोकप्रिय उत्तर है कि यह खराब क्यों है


लेकिन अगर मैं इस कोड को तरीकों में अलग करता हूं

public void SomeLongMethod()
{
    Task1();

    Task2();
}

private void Task1()
{
    // Some task #1
    ...
}

private void Task2()
{
    // Some task #1
    ...
}

मैं निम्नलिखित मुद्दों को देखता हूं:

  • प्रदूषण की वर्ग परिभाषा का दायरा उन परिभाषाओं के साथ है जो आंतरिक रूप से एक ही विधि द्वारा उपयोग किए जाते हैं और जिसका अर्थ है कि मुझे कहीं Task1और दस्तावेज़ करना चाहिए और Task2केवल SomeLongMethod(या मेरे कोड को पढ़ने वाले प्रत्येक व्यक्ति को इस विचार को समझना होगा) के आंतरिक के लिए अभिप्रेत है ।

  • प्रदूषणकारी IDE स्वतः पूर्ण (उदा। तरीके) जो एकल SomeLongMethodविधि के अंदर केवल एक बार उपयोग किया जाएगा ।


इसलिए अगर मैं इस विधि कोड को स्थानीय कार्यों में अलग करता हूं

public void SomeLongMethod()
{
    Task1();

    Task2();

    void Task1()
    {
        // Some task #1
        ...
    }

    void Task2()
    {
        // Some task #1
        ...
    }
}

तब इसमें अलग-अलग विधियों की कमियां नहीं होती हैं, लेकिन यह मूल विधि की तुलना में बेहतर (कम से कम मेरे लिए) नहीं दिखता है।


आपके लिए कौन सा संस्करण SomeLongMethodअधिक सुपाच्य और पठनीय है और क्यों?



@ मेरा प्रश्न c # के लिए विशिष्ट है , जावा नहीं । मेरी मुख्य चिंता क्लासिक विधि बनाम स्थानीय कार्य के बारे में है, न केवल तरीकों में अलग है या नहीं।
वादिम ओविचनिकोव

@gnat AFAIK जावा (C # के विपरीत) नेस्टेड फ़ंक्शन का समर्थन नहीं करता है।
वादिम ओविचनिकोव

1
निजी कीवर्ड निश्चित रूप से आपके 'क्लास डेफिनेशन स्कोप' की सुरक्षा करता है?
इवान

1
रुको ...... तुम्हारी कक्षा कितनी बड़ी है?
इवान

जवाबों:


13

स्व-निहित कार्यों को स्व-निहित विधियों में ले जाना चाहिए। इस लक्ष्य को पार करने के लिए कोई बड़ी खामी नहीं है।

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

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


तो आप तरीकों के लिए हैं, स्थानीय कार्यों के लिए नहीं, हाँ?
वादिम ओविचिनिकोव

2
@VadimOvchinnikov एक आधुनिक कोड-तह आईडीई के साथ थोड़ा अंतर है। एक स्थानीय फ़ंक्शन का सबसे बड़ा लाभ यह है कि यह चर को एक्सेस कर सकता है अन्यथा आपको मापदंडों के रूप में पास करना होगा, लेकिन अगर उनमें से बहुत से हैं, तो कार्य वास्तव में शुरू करने के लिए स्वतंत्र नहीं थे।
किलिआन फोथ

6

मुझे कोई तरीका पसंद नहीं है। आपने कोई व्यापक संदर्भ प्रदान नहीं किया लेकिन अधिकांश बार ऐसा दिखता है:

आपके पास एक वर्ग है जो एक ही परिणाम में कई सेवाओं की शक्ति को मिलाकर कुछ काम करता है।

class SomeClass
{
    private readonly Service1 _service1;
    private readonly Service2 _service2;

    public void SomeLongMethod()
    {
        _service1.Task1();
        _service2.Task2();       
    }
}

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

class Service1
{
    public void Task1()
    {
        // Some task #1
        ...
    }

    private void SomeHelperMethod() {}
}

class Service2
{
    void Task2()
    {
        // Some task #1
        ...
    }
}

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


2

विधि के भीतर फ़ंक्शन बनाने के साथ समस्या यह है कि यह विधि की लंबाई को कम नहीं करता है।

यदि आप सुरक्षा का अतिरिक्त स्तर 'निजी से विधि' चाहते हैं तो आप एक नया वर्ग बना सकते हैं

public class BigClass
{
    public void SomeLongMethod();

    private class SomeLongMethodRunner
    {
        private void Task1();
        private void Task2();
    }
}

लेकिन कक्षाओं में कक्षाएं एक बड़ी बदसूरत हैं: /


2

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

यह स्थानीय कार्यों का उपयोग करने के पक्ष में बोलता है।


1
hmm निश्चित रूप से कोड का पुन: उपयोग कर रहा है == कई कॉलर्स के बीच एक विधि साझा कर रहा है। इसका दायरा अधिकतम करना
इवान

1

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

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

स्थानीय कार्य पेज कि राज्यों:

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

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

संक्षेप में, सामान्य तौर पर, मैं तरीकों में अलग करने का पक्ष लूंगा, लेकिन एमएस ने एक कारण के लिए स्थानीय कार्यों को लिखा, इसलिए मैं निश्चित रूप से यह नहीं कहूंगा कि मैं उनका उपयोग नहीं करूंगा

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