2009-03-05 8 views
5

मुझे यह दो बार सामना करना पड़ा, और मुझे आश्चर्य हुआ कि परिपत्र संदर्भों को हल करने के लिए ओओ तरीका क्या है। इसके द्वारा मेरा मतलब है कि कक्षा ए में एक सदस्य के रूप में कक्षा बी है, और बी में बदले में कक्षा ए सदस्य है।ओओपी में क्रॉस रेफरेंस को कैसे हल करें?

इसका एक उदाहरण क्लास व्यक्ति होगा जिसमें सदस्य के रूप में व्यक्ति पति/पत्नी होगा।

Person jack = new Person("Jack"); 
Person jill = new Person("Jill"); 
jack.setSpouse(jill); 
jill.setSpouse(jack); 

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

Product pc = new Product("pc"); 
Product monitor = new Product("monitor"); 
Product tv = new Product("tv"); 
pc.setSeeAlso({monitor, tv}); 
monitor.setSeeAlso({pc}); 
tv.setSeeAlso(null); 

(इन उत्पादों रहे हैं सिर्फ एक बिंदु बनाने के लिए, इस मुद्दे मौसम के बारे में नहीं है या नहीं कुछ उत्पादों एक दूसरे से संबंधित हैं)

यह सामान्य रूप में OOP में बुरा डिजाइन होगा? क्या सभी ओओपी भाषाएं इसे अनुमति देंगी, या क्या यह सिर्फ खराब अभ्यास है? यदि यह बुरा अभ्यास है, तो इसे हल करने का सबसे अच्छा तरीका क्या होगा?

+0

@ जोन लिमजाप: टाइपो को सही करने के लिए धन्यवाद। – tehvan

उत्तर

1

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

2

आपके द्वारा दिए गए उदाहरण उचित ओओ डिजाइन के उदाहरण हैं (वैसे भी)।

आपके द्वारा वर्णित क्रॉस-रेफरेंसिंग समस्या किसी भी डिजाइन प्रक्रिया का एक आर्टिफैक्ट नहीं है, लेकिन चीजों की वास्तविक जीवन विशेषता है जो आप वस्तुओं के रूप में प्रतिनिधित्व कर रहे हैं, इसलिए मुझे कोई समस्या नहीं है।

आपने क्या अनुभव किया है जिससे आपको यह इंप्रेशन दिया गया है कि यह दृष्टिकोण खराब-डिजाइन है?

अपडेट 11 मार्च: - किसी अन्य वस्तु प्रबंधन के लिए जिम्मेदार

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

एक उदाहरण डेल्फी की टीकंपोनेंट क्लास है, जो कैस्केडिंग समर्थन प्रदान करता है - मूल घटक को नष्ट करता है, और सभी स्वामित्व वाले घटकों को भी नष्ट कर दिया जाता है।

आप एक ऐसी प्रणाली पर काम कर रहे हैं, यह सवाल में वर्णित संदर्भ पाश के प्रकार गरीब डिजाइन माना जा सकता है कोई स्पष्ट मालिक है, क्योंकि, कोई भी जीवन काल प्रबंधन के लिए जिम्मेदार आपत्ति है।

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

+0

यह मेरे लिए वास्तविक जीवन की तरह लगता है, मैं बस सोच रहा था कि वीएम ऑब्जेक्ट का पीछा करने में भ्रमित नहीं होंगे ... एक व्यक्ति को लोड करना, उस व्यक्ति के पति को फिर से लोड करना, उस व्यक्ति के पति/पत्नी को ... यह एक शाश्वत पाश है। बस सोच रहा है कि क्या सभी वीएम ठीक से संभाल सकते हैं। – tehvan

+0

वीएम? आप रनटाइम का मतलब है? केवल सिस्टम की गणना (COM या रोल-उदाहरण के लिए, अपने स्वयं के स्मार्ट पॉइंटर्स), किसी वास्तविक जीसी सिस्टम –

+0

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

1

मुख्य समस्या यह एक समस्या है यदि यह सामना करने या बनाए रखने में बहुत भ्रमित हो जाता है, क्योंकि यह स्पेगेटी कोड का एक रूप बन सकता है।

हालांकि, अपने उदाहरणों को छूने के लिए;

देखें इसके अलावा पूरी तरह से वैध है अगर यह एक सुविधा आप अपने कोड में की जरूरत है - यह अन्य मदों के लिए संकेत (या संदर्भ) की एक सरल सूची एक उपयोगकर्ता में रुचि हो सकती है

इसी तरह यह है। पति/पत्नी को जोड़ने के लिए पूरी तरह से मान्य है, क्योंकि यह सरल असली दुनिया संबंध है जो आपके कोड को बनाए रखने वाले किसी व्यक्ति को भ्रमित नहीं करेगा।

मैंने इसे हमेशा संभावित कोड गंध के रूप में देखा है, या शायद एक कदम वापस लेने के लिए एक चेतावनी और मैं जो कर रहा हूं उसे तर्कसंगत बना रहा हूं।

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

-2

इसे ठीक करने का एक तरीका किसी ऑब्जेक्ट के माध्यम से अन्य ऑब्जेक्ट को संदर्भित करना है।

उदा।

Person jack = new Person(new PersonId("Jack")); 
Person jill = new Person(new PersonId("Jill")); 
jack.setSpouse(jill.getId()); 
jill.setSpouse(jack.getId()); 

मैं यह नहीं कह रहा कि यह एक आदर्श समाधान है, लेकिन यह परिपत्र संदर्भों को रोक देगा। आप संबंध मॉडल के ऑब्जेक्ट संदर्भ के बजाय ऑब्जेक्ट का उपयोग कर रहे हैं।

+0

यह डेटाबेस की तरह बहुत ज्यादा सोच रहा है। किसी ऑब्जेक्ट का संदर्भ सेट करना कम काम के साथ एक ही चीज़ को पूरा करता है। – Boden

+0

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

0

मुझे नहीं लगता कि सर्कुलर संदर्भ इस तरह की समस्या है।

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

1

मुझे नहीं लगता कि यह क्रॉस रेफरेंसिंग का एक उदाहरण है।

क्रॉस आमतौर पर संदर्भित इस मामले से संबंधित है:

class A 
{ 
    public void MethodA(B objectB) 
    { 
     objectB.SomeMethodInB(); 
    } 
} 

class B 
{ 
    public void MethodB(A objectA) 
    { 
     objectA.SomeMethodInA(); 
    } 
} 

इस मामले की प्रत्येक वस्तु तरह एक दूसरे के लिए "में पहुंचता है" में; एक कॉल बी, बी कॉल ए, और वे कसकर युग्मित हो जाते हैं। यदि ए और बी विभिन्न पैकेज/नेमस्पेस/असेंबली में हैं तो यह और भी बदतर हो जाता है; कई मामलों में वे संकलन समय त्रुटियों का निर्माण करेंगे क्योंकि असेंबली रैखिक रूप से संकलित की जाती है।

हल करने का तरीका या तो ऑब्जेक्ट वांछित विधि के साथ एक इंटरफेस को लागू करना है।

आपके मामले में आप केवल "में पहुँच रहा है" में से एक स्तर है:

public Class Person 
{ 
    public void setSpouse(Person person) 
    { ... } 
} 

मुझे नहीं लगता कि यह अनुचित है, न ही और भी पार संदर्भित/वृत्तीय संदर्भ का मामला।

0

अन्य ऑब्जेक्ट्स का संदर्भ देना एक वास्तविक बुरा ओओ डिज़ाइन बिल्कुल नहीं है। इस तरह राज्य को प्रत्येक वस्तु के भीतर प्रबंधित किया जाता है।

अंगूठे का एक अच्छा नियम डेमेटर का कानून है। LoD (पेपरबॉय और वॉलेट) का यह सही पेपर देखें: click here

संबंधित मुद्दे