इटरेटर पैटर्न - आंतरिक प्रतिनिधित्व को उजागर नहीं करना क्यों महत्वपूर्ण है?


24

मैं C # Design Pattern Essentials पढ़ रहा हूँ । मैं वर्तमान में पुनरावृत्ति पैटर्न के बारे में पढ़ रहा हूँ।

मैं पूरी तरह से समझता हूं कि कैसे लागू किया जाए, लेकिन मैं इसके महत्व को नहीं समझता या उपयोग का मामला नहीं देखता। पुस्तक में एक उदाहरण दिया गया है जहां किसी को वस्तुओं की सूची प्राप्त करने की आवश्यकता होती है। वे सार्वजनिक संपत्ति जैसे कि IList<T>या ए को उजागर करके ऐसा कर सकते थे Array

किताब लिखता है

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

आंतरिक प्रतिनिधित्व क्या है? तथ्य यह है arrayया IList<T>? मैं वास्तव में नहीं जानता कि यह उपभोक्ता के लिए एक बुरी बात क्यों है (प्रोग्रामर इसे कॉल करता है) यह जानने के लिए ...

पुस्तक तब कहती है कि यह पैटर्न इसके GetEnumeratorकार्य को उजागर करके काम करता है , इसलिए हम GetEnumerator()'सूची' को इस तरह से कॉल और उजागर कर सकते हैं ।

मुझे लगता है कि इस पैटर्न में कुछ स्थितियों में एक जगह (सभी की तरह) है, लेकिन मैं यह देखने में विफल रहता हूं कि कहां और कब।



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

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

मान लीजिए कि हमारे पास एक अच्छा "इंटरफ़ेस" Fहै जो मुझे ( और ) का ज्ञान देता है a, bऔर c। सब ठीक है और अच्छा है, कई चीजें हो सकती हैं जो अलग हैं लेकिन सिर्फ Fमेरे लिए। विधि के बारे में सोचें "अड़चन" या एक अनुबंध के खंड Fकरने के लिए कक्षाएं करता है। मान लीजिए कि हम एक dहालांकि जोड़ते हैं , क्योंकि हमें इसकी आवश्यकता है। यह एक अतिरिक्त बाधा जोड़ता है, हर बार जब हम ऐसा करते हैं तो हम अधिक से अधिक एस पर थोपते हैं F। आखिरकार (सबसे खराब स्थिति) केवल एक चीज हो सकती है, Fइसलिए हमारे पास ऐसा नहीं हो सकता है। और Fऐसा करने के लिए केवल एक ही रास्ता है।
एलेक टील

@captainman, क्या शानदार टिप्पणी है। हां मैं देखता हूं कि कई चीजों को 'अमूर्त' क्यों किया जाता है, लेकिन जानने और भरोसा करने के बारे में ट्विस्ट है ... स्पष्ट रूप से .... शानदार। और एक महत्वपूर्ण अंतर जिसे मैंने आपके पोस्ट को पढ़ने तक नहीं माना था।
MyDaftQuestions

जवाबों:


56

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

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

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

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


12
Exposing the concrete type Array usually creates many additional promises, e.g. that you can sort the collection by a function of your own choosing...- प्रतिभाशाली। मैंने अभी इसके बारे में नहीं सोचा था। हाँ, यह एक 'पुनरावृत्ति' और केवल एक पुनरावृत्ति लाता है!
MyDaftQuestions

18

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

पुनरावृत्तियों के ठोस प्रकार को उजागर करने के साथ समस्या - या यहां तक ​​कि जैसे इंटरफेस IList<T>- उन वस्तुओं में नहीं है जो उन्हें उजागर करते हैं, लेकिन उन तरीकों में जो उनका उपयोग करते हैं। उदाहरण के लिए, मान लें कि आपके पास Foos की सूची को मुद्रित करने के लिए एक फ़ंक्शन है :

void PrintFoos(IList<Foo> foos)
{
    foreach (foo in foos)
    {
        Console.WriteLine(foo);
    }
}

आप उस फ़ंक्शन का उपयोग केवल फू की सूचियों को प्रिंट करने के लिए कर सकते हैं - लेकिन केवल अगर वे लागू करते हैं IList<Foo>

IList<Foo> foos = //.....
PrintFoos(foos);

लेकिन क्या होगा अगर आप सूची के हर समान-अनुक्रमित आइटम को प्रिंट करना चाहते हैं ? आपको एक नई सूची बनाने की आवश्यकता होगी:

IList<Foo> everySecondFoo = new List<T>();
bool isIndexEven = true;
foreach (foo; foos)
{
    if (isIndexEven)
    {
        everySecondFoo.Add(foo);
    }
    isIndexEven = !isIndexEven;
}
PrintFoos(everySecondFoo);

यह काफी लंबा है, लेकिन LINQ के साथ हम इसे वन-लाइनर के लिए कर सकते हैं, जो वास्तव में अधिक पठनीय है:

PrintFoos(foos.Where((foo, i) => i % 2 == 0).ToList());

अब, क्या आपने .ToList()अंत में नोटिस किया ? यह आलसी क्वेरी को एक सूची में परिवर्तित करता है, इसलिए हम इसे पास कर सकते हैं PrintFoos। इसके लिए एक दूसरी सूची के आवंटन की आवश्यकता होती है, और आइटम पर दो पास (पहली सूची पर एक और दूसरी सूची बनाने के लिए, और दूसरी सूची पर इसे मुद्रित करने के लिए)। इसके अलावा, अगर हमारे पास यह है:

void Print6Foos(IList<Foo> foos)
{
    int counter = 0;
    foreach (foo in foos)
    {
        Console.WriteLine(foo);
        ++ counter;
        if (6 < counter)
        {
            return;
        }
    }
}

// ........

Print6Foos(foos.Where((foo, i) => i % 2 == 0).ToList());

क्या होगा अगर foosहजारों प्रविष्टियाँ हैं? हमें उन सभी के माध्यम से जाना होगा और उनमें से केवल 6 को प्रिंट करने के लिए एक बड़ी सूची आवंटित करनी होगी!

Entererators दर्ज करें - Iterator पैटर्न का C # संस्करण। हमारे कार्य को किसी सूची को स्वीकार करने के बजाय, हम इसे स्वीकार करते हैं Enumerable:

void Print6Foos(Enumerable<Foo> foos)
{
    // everything else stays the same
}

// ........

Print6Foos(foos.Where((foo, i) => i % 2 == 0));

अब Print6Foosसूची के पहले 6 मदों पर आलसी पुनरावृति कर सकते हैं, और हमें इसके बाकी हिस्सों को छूने की आवश्यकता नहीं है।

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


6

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

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

यही कारण है कि एनकैप्सुलेशन किसी भी nontrivial सॉफ़्टवेयर डिज़ाइन के सबसे महत्वपूर्ण पहलुओं में से एक है।


6

जितना कम आप कहेंगे, उतना कम आपको कहना पड़ेगा।

जितना कम आप पूछेंगे, आपको उतना कम बताया जाएगा।

यदि आपका कोड केवल उजागर होता है IEnumerable<T>, जो केवल समर्थन करता है तो GetEnumrator()इसे किसी अन्य कोड द्वारा प्रतिस्थापित किया जा सकता है जो समर्थन कर सकता है IEnumerable<T>। यह लचीलापन जोड़ता है।

यदि आपका कोड केवल IEnumerable<T>इसका उपयोग करता है तो इसे लागू करने वाले किसी भी कोड द्वारा समर्थित किया जा सकता है IEnumerable<T>। फिर से, अतिरिक्त लचीलापन है।

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


अच्छा स्पष्ट जवाब। इसमें बहुत उपयुक्त है कि आप इसे कम रखें, और इसलिए पहले वाक्य में आपकी सलाह का पालन करें। वाहवाही!
डैनियल हॉलिनरेके

0

एक शब्दांकन मैं दर्पण का उपयोग करना पसंद करता हूं @CaptainMan की टिप्पणी: "आंतरिक विवरण जानने के लिए उपभोक्ता के लिए यह ठीक है। ग्राहक के लिए आंतरिक विवरण जानना आवश्यक है।"

यदि किसी ग्राहक को अपने कोड में arrayया IList<T>उनके प्रकार, जब उन प्रकार के आंतरिक विवरण थे, तो उपभोक्ता को उन्हें सही प्राप्त करना होगा। यदि वे गलत हैं, तो उपभोक्ता संकलन नहीं कर सकता है, या गलत परिणाम भी प्राप्त कर सकता है। यह उसी व्यवहार को उत्पन्न करता है जैसे "हमेशा कार्यान्वयन विवरण छिपाते हैं क्योंकि आप उन्हें उजागर नहीं करना चाहिए," लेकिन उजागर नहीं करने के फायदे पर खुदाई करना शुरू करते हैं। यदि आप एक कार्यान्वयन विवरण को कभी उजागर नहीं करते हैं, तो आपका ग्राहक कभी भी इसका उपयोग करके अपने आप को एक बंधन में नहीं डाल सकता है!

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

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

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


1
पुन: "या एक विकास के माहौल पर विचार करें जहां आपके पास 'अच्छा एपीआई' बनाने के लिए समय नहीं है, और तुरंत चीजों का उपयोग करने की आवश्यकता है": यदि आप अपने आप को ऐसे वातावरण में पाते हैं, और किसी कारण से नहीं छोड़ना चाहते हैं ( या यदि आप ऐसा नहीं कर रहे हैं तो निश्चित नहीं है), मैं ' डेथ इम्पॉसिबल' प्रोजेक्ट्स को पूरा करने के लिए डेथ मार्च: द कम्प्लीट सॉफ्टवेयर डेवलपर गाइड बुक की सिफारिश करता हूं । इस विषय पर उत्कृष्ट सलाह है। (इसके अलावा, मैं आपके मन को छोड़ने के बारे में नहीं बदलने की सलाह देता हूं।)
4

@ruakh मैंने पाया है कि यह समझना हमेशा महत्वपूर्ण है कि ऐसे वातावरण में कैसे काम करें जहाँ आपके पास अच्छा एपीआई बनाने का समय नहीं है। सच कहूँ तो, जितना हम हाथीदांत टॉवर दृष्टिकोण से प्यार करते हैं, असली कोड वह है जो वास्तव में बिलों का भुगतान करता है। जितनी जल्दी हम यह स्वीकार कर सकते हैं, उतनी ही जल्दी हम अपने सटीक वातावरण से मेल खाने के लिए उत्पादक कोड के साथ एपीआई गुणवत्ता को संतुलित करते हुए एक संतुलन के रूप में सॉफ्टवेयर से संपर्क करना शुरू कर सकते हैं। मैंने बहुत से युवा डेवलपर्स को आदर्शों की गड़बड़ी में फँसा हुआ देखा है, उन्हें यह महसूस नहीं हुआ कि उन्हें फ्लेक्स करने की आवश्यकता है। (मैं भी उस युवा डेवलपर रहा हूँ .. अभी भी "अच्छा एपीआई" डिजाइन के 5 साल से ठीक हो रहा है)
Cort Ammon -

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

1
@ मेरे पास जो कुछ भी है वह यह है कि "अच्छे एपीआई" के बिना अच्छा कोड बनाना संभव है। यदि अवसर दिया जाए, तो अच्छे एपीआई अच्छे होते हैं, लेकिन आवश्यकता के रूप में उन्हें मानने से ज्यादा संघर्ष होता है। विचार करें: मानव शरीर के लिए एपीआई भयावह है, लेकिन हमें अभी भी लगता है कि वे इंजीनियरिंग के बहुत अच्छे करतब दिखा रहे हैं =)
कॉर्ट अमोन -

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

0

आप जरूरी नहीं जानते कि आपके डेटा का आंतरिक प्रतिनिधित्व क्या है - या भविष्य में बन सकता है।

मान लें कि आपके पास एक डेटा स्रोत है, जिसे आप एक सरणी के रूप में दर्शाते हैं, आप लूप के लिए नियमित रूप से उस पर पुनरावृति कर सकते हैं।

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

यदि आपके पास केवल एक ही लूप है, तो आप अपने कोड को आसानी से संशोधित कर सकते हैं डेटा ऑब्जेक्ट तक पहुंचने के लिए जिस तरह से यह एक्सेस होने की उम्मीद करता है।

यदि आपके पास डेटा ऑब्जेक्ट तक पहुंचने के लिए 1000 कक्षाएं हैं, तो अब आपके पास बड़ी रिफैक्टिंग समस्या है।

सूची आधारित डेटा स्रोत तक पहुँचने के लिए एक इटेरेटर एक मानक तरीका है। यह एक सामान्य इंटरफ़ेस है। इसका उपयोग करने से आपका कोड डेटा स्रोत अज्ञेय बन जाएगा।

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