क्या कई परतों के माध्यम से उदाहरणों को पारित करना बुरा है?


60

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

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

जवाबों:


54

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

  • डेटाबेस ऑब्जेक्ट्स को कभी भी उच्च परतों तक नहीं जाना चाहिए। मैंने .NET के डेटा एडेप्टर वर्ग, एक डीबी-एक्सेस क्लास, और यूआई परत तक इसे पास करने के बजाय, डीएएल में डेटा एडेप्टर का उपयोग करने, डीटीओ या डेटासेट बनाने और इसे पास करने के लिए प्रोग्राम देखा है । DB एक्सेस DAL का डोमेन है।
  • यूआई वस्तुओं को, निश्चित रूप से, यूआई परत तक सीमित होना चाहिए। फिर से, मैंने इसका उल्लंघन देखा है, लिस्टबॉक्स् के साथ आबादी के डेटा के साथ लिस्ट किए गए दोनों बीओबी लेयर के बजाय, इसकी सामग्री की एक सरणी / डीटीओ, और (मेरी एक विशेष पसंदीदा), एक डीएएल वर्ग जो पदानुक्रमित डेटा प्राप्त करता है। DB, और एक पदानुक्रमित डेटा संरचना को वापस करने के बजाय, यह सिर्फ एक TreeView ऑब्जेक्ट को बनाया और पॉप्युलेट किया गया, और इसे UI से वापस एक फॉर्म में गतिशील रूप से जोड़ा गया।

हालाँकि, यदि आप जिन उदाहरणों से गुजर रहे हैं, वे स्वयं डीटीओ या संस्थाएँ हैं, तो यह ठीक है।


1
यह चौंकाने वाला लग सकता है, लेकिन .NET के अंधेरे शुरुआती दिनों में, जो आमतौर पर अनुशंसित अभ्यास था और शायद सबसे बेहतर था कि अन्य स्टैक क्या कर रहे थे।
वायट बार्नेट

1
मैं असहमत हूं। यह सच है कि Microsoft ने सिंगल-लेयर ऐप के अभ्यास का समर्थन किया जहां Winforms क्लाइंट ने DB को एक्सेस किया, और डेटा एडेप्टर को अदृश्य नियंत्रण के रूप में सीधे रूप में जोड़ा गया, लेकिन यह ओपी के एन-टियर सेटअप से अलग सिर्फ एक विशिष्ट वास्तुकला है। । लेकिन एक बहुपरत आर्किटेक्चर में, और यह .NET से पहले भी VB6 / DNA के लिए सही था, DB ऑब्जेक्ट DB लेयर में रहे।
अवनेर शाहर-कश्तन

स्पष्ट करने के लिए: आपने अपने "डेटा लेयर" से लोगों को सीधे यूआई (आपके उदाहरण में, लिस्टबॉक्स) में प्रवेश करते देखा है? मुझे नहीं लगता कि मैं प्रोडक्शन कोड में इस तरह का उल्लंघन कर रहा हूं .. वाह ..
सिमोन व्हाइटहेड

7
@SimonWhitehead बिल्कुल। वे लोग जो लिस्टबॉक्स और एरे के अंतर के बारे में फ़र्ज़ी थे, और एक लिस्ट के रूप में लिस्टबॉक्स का इस्तेमाल किया। यह एक ऐसा क्षण था जिसने मुझे यह महसूस करने में मदद की कि मैं कितनी अदृश्य धारणाएं बनाता हूं जो दूसरों के लिए सहज नहीं हैं।
अवनर शाहर-कश्तन

1
@SimonWhitehead - जी हाँ, मैंने देखा है कि VB6 और VB.NET फ्रेमवर्क 1.1 और 2.0 कार्यक्रमों में और इस तरह के राक्षसों को बनाए रखने का काम सौंपा गया है। यह बहुत बदसूरत हो जाता है, बहुत जल्दी।
jfrankcarr 15

15

दिलचस्प है कि किसी ने अभी तक अपरिवर्तनीय वस्तुओं के बारे में बात नहीं की है। मैं तर्क दूंगा कि सभी विभिन्न परतों के माध्यम से एक अपरिवर्तनीय वस्तु को पारित करना वास्तव में एक अच्छी बात है कि प्रत्येक परत पर बहुत सारी छोटी वस्तुओं का निर्माण होता है।

उनके ब्लॉग पर एरिक लिपर्ट द्वारा अपरिवर्तनीयता के कुछ महान विचार-विमर्श हैं

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


13

ऑब्जेक्ट इंस्टेंस को पास करना एक सामान्य बात है। यह राज्य (यानी उदाहरण चर) रखने की आवश्यकता को कम करता है और इसके निष्पादन संदर्भ से कोड को डिकोड करता है।

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


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

8

हो सकता है कि मामूली हो, लेकिन इस संदर्भ को कहीं एक परत में रखने का जोखिम है, जो संभवतः बाद में एक झूलने वाला संदर्भ या स्मृति रिसाव का कारण बनता है।


आपकी बात सही है, लेकिन ओपी की शब्दावली ("पासिंग ऑब्जेक्ट इंस्टैंस") से मुझे यह समझ में आता है कि या तो वह मानों (पॉइंटर्स नहीं) को पार कर रहा है या वह कचरा एकत्र करने वाले वातावरण (जावा, सी #, पायथन, गो,) के बारे में बात कर रहा है। ..)।
मोहम्मद देहघन

7

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


यह दिलचस्प लगता है, मैं पहले से ही निर्माता इंजेक्शन का उपयोग करता हूं, और मुझे लगता है कि मेरे उच्च स्तर के घटक निम्न स्तर के घटकों को नियंत्रित करते हैं। उदाहरणों के आसपास ले जाने से बचने के लिए आप IOC कंटेनर का उपयोग कैसे करते हैं?
पुकल

मुझे लगता है कि मुझे यहाँ जवाब मिला: martinfowler.com/articles/injection.html
Puckl

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

4

डेटा को गर्त में समतल करना एक बुरी बात नहीं है, यह वास्तव में एकमात्र तरीका है कि एक स्तरित प्रणाली स्तरित संरचना का उल्लंघन किए बिना काम कर सकती है। संकेत यह है कि समस्याएं तब हैं जब आप अपना लक्ष्य प्राप्त करने के लिए एक ही परत में कई वस्तुओं के आसपास अपना डेटा पास कर रहे हैं।


3

त्वरित उत्तर: नहीं है कुछ भी गलत नहीं वस्तुओं के उदाहरण पारित करने में। जैसा कि उल्लेख किया गया है, बिंदु इस संदर्भ को सभी परतों में संभवतः एक झूलने वाले संदर्भ या मेमोरी लीक के कारण छोड़ना है।

हमारी परियोजनाओं में, हम इस अभ्यास का उपयोग परतों के बीच डीटीओ (डेटा ट्रांसफर ऑब्जेक्ट) को पारित करने के लिए करते हैं और यह बहुत सहायक अभ्यास है। सारांश जानकारी के लिए, हम एक बार और जटिल बनाने के लिए अपनी dto वस्तुओं का पुन: उपयोग करते हैं।


3

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

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

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

तो इस मामले में मुझे नहीं लगता कि यह वस्तु उदाहरण है जो आपके आस-पास उछाला जा रहा है जो आपको गुस्सा दिला सकता है। यह है कि कैप्टन पिकार्ड ताना-बाना को चालू करने के लिए इंजन कक्ष में नीचे चल रहा है, निर्देशांक को साजिश करने के लिए पुल तक वापस चल रहा है, और फिर केवल कहने के बजाय ढाल चालू करने के बाद "पंच-इट" बटन को दबाएं। हमें ताना 9 पर ग्रह के लिए। यह बनाओ। और उसके चालक दल के विवरण को छाँटने दें। क्योंकि जब वह इसे इस तरह से संभालता है, तो वह हर जहाज के लेआउट को जाने बिना और सब कुछ कैसे काम करता है, इसके बारे में वह बेड़े में किसी भी जहाज की कप्तानी कर सकता है। और वह अंततः IMO के लिए शूट करने वाली सबसे बड़ी OOP डिज़ाइन जीत है।


2

यह काफी सामान्य डिजाइन है जो समाप्त हो रहा है, हालांकि आपके पास विलंबता समस्या हो सकती है यदि आपका ऐप उस तरह की चीज़ के प्रति संवेदनशील है।


2

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


2

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

एक संभव समाधान नियंत्रक वर्ग में नेस्टेड संदर्भों को "समतल" करना है।

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

यह वास्तव में कैसे लागू किया जाता है (या यदि यह एक वैध समाधान है) प्रणाली के वर्तमान डिजाइन पर निर्भर है, जैसे:

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

यह एक ऐसा मुद्दा है जो मुझे GXT क्लाइंट के लिए MVC डिज़ाइन पैटर्न में मिला है। हमारे जीयूआई घटकों में कई परतों के लिए नेस्टेड जीयूआई घटक शामिल थे। जब मॉडल डेटा को अपडेट किया गया था, तो हमने इसे कई परतों से गुजरते हुए समाप्त कर दिया, जब तक कि यह उपयुक्त घटक (एस) तक नहीं पहुंच गया। इसने GUI घटकों के बीच अवांछित युग्मन पैदा किया क्योंकि अगर हम मॉडल डेटा को स्वीकार करने के लिए एक नया GUI घटक वर्ग चाहते थे, तो हमें उन सभी GUI घटकों में मॉडल डेटा को अपडेट करने के लिए तरीके बनाने थे जिनमें नई कक्षा सम्‍मिलित थी।

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


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