मैं एक साधारण प्रोग्राम तैयार करने के तरीके से असहज हूं। FileParser
ऑब्जेक्ट है जिसमें OnFileOpened
, OnLineParsed
, और OnFileClosed
ईवेंट हैं, और कई ऑब्जेक्ट्स जो फ़ाइल की सामग्री के आधार पर छोटी फ़ाइलों को बनाते हैं जो FileParser
पार्स हैं।ऑडिओमैटिक सी # ऑब्जेक्ट के लिए केवल इंटरैक्टिंग के बावजूद घटनाओं पर पंजीकृत होने के बावजूद
FileParser
देख रहे ऑब्जेक्ट्स उनके कन्स्ट्रक्टर में FileParser
ईवेंट के साथ अपने तरीकों को पंजीकृत करते हैं।
ParsedFileFrobber(FileParser fileParser)
{
fileParser.OnFileOpen += this.OpenNewFrobFile;
fileParser.OnLineParsed += this.WriteFrobbedLine;
fileParser.OnFileClose += this.CloseFrobFile;
}
उसके बाद, ParsedFileFrobber
बस आगे स्पष्ट सहभागिता के बिना चीजों के साथ पर हो जाता है।
जो चीज मुझे परेशान करती है वह यह है कि मुख्य कार्यक्रम केवल ParsedFileFrobber
असाइन करता है और मूल रूप से कन्स्ट्रक्टर के वापसी मूल्य का उपयोग नहीं करता है।
var fileParser = new FileParser(myFilename);
var parsedFileFrobber = new ParsedFileFrobber(fileParser);
// No further mentions of parsedFileFrobber.
यह काम करता है, लेकिन रीशेर्पर इस बारे में शिकायत करता है, जो कम से कम मुझे सोचने के लिए रोक देता है। असल में, मुझे कन्स्ट्रक्टर के नतीजे के लिए एक वैरिएबल असाइन करने की भी आवश्यकता नहीं है, क्योंकि जीसी इवेंट हैंडलर संदर्भों की योग्यता से ParsedFileFrobber
जीवित रखेगी, लेकिन एक नंगे new
मेरे लिए बहुत गलत लग रहा है। (यह अभी भी संकलित और सही ढंग से चलता है।)
var fileParser = new FileParser(myFilename);
new ParsedFileFrobber(fileParser);
क्या यह कोई समस्या है? क्या यह एक विरोधी पैटर्न या कोड गंध है? क्या सी # में ऐसा करने का एक बेवकूफ तरीका है?
धन्यवाद!
स्पष्टीकरण मददगार टिप्पणियाँ करने के लिए धन्यवाद:
1) क्यों रिश्ते को उलटने के नहीं? कोडी ग्रे
आह, उदाहरण थोड़ा सा सरल था। मेरे पास वास्तव में ParsedFileFrobber
है, एक ParsedFileGrobber
, और ParsedFileBrobber
है। रिश्ते को बदलने से FileParser
सभी 3 पर निर्भर करेगा। (इसके अलावा, शुरुआत में केवल एक फ्रोबबर और ग्रोबबर था, लेकिन बाद में ब्रोबबर की आवश्यकता थी, और अभी भी एक ड्रोबबर और आगे के लिए गुंजाइश है।) मुझे लगता है कि यह स्वाद का विषय है कि सदस्यता के कोड FileParser
कन्स्ट्रक्टर में या ParsedFileFrobber
, ParsedFileGrobber
, औरकन्स्ट्रक्टर में होते हैं, लेकिन मेरी प्राथमिकता FileParser
जितना संभव हो सके अज्ञेयवादी रखने की कोशिश करना है।
2) कन्स्ट्रक्टर को स्थिर विधि में क्यों नहीं ले जाएं (और कन्स्ट्रक्टर को निजी बनाएं)? हंस पासेंट
मैं देख सकता हूं कि कक्षा के निजी आंतरिक कार्यों में संभावित रूप से अनजान उपयोग को दूर करने के लिए यह कैसे अच्छी तरह से तैयार है, जो अच्छी सलाह है। हालांकि, यह अभी भी नंगे new
या कन्स्ट्रक्टर के रिटर्न वैल्यू का एकमात्र निर्दिष्ट संदर्भ होगा। खैर, अगर यह एक बड़ी समस्या नहीं है, तो बदसूरत कोड को छिपाने के लिए यह समझ में आता है। (संदर्भ के लिए, मैं Dispose
विधि घटनाओं से सदस्यता समाप्ति के साथ ParsedFileFrobber
एक IDisposable
बनाने के लिए किया था, तो यह frobbing को समाप्त कर दिया जा सकता है।)
आप सभी टिप्पणीकर्ताओं को धन्यवाद!
मुझे पूरी तरह से यकीन नहीं है कि मैं डिजाइन को समझता हूं, लेकिन मेरा पहला सवाल होगा, रिश्ते को क्यों नकारें? वर्तमान में, आपने ParsedFileFrobber FileParser पर निर्भर है, लेकिन फिर कभी भी पार्सडफ़ाइलफ़ोबबर के उदाहरण का उपयोग कभी नहीं करें। इसके बजाय फ़ाइलपर्सर को पार्सडफाइलफ़ोबबर पर निर्भर क्यों नहीं करते हैं, क्योंकि आप (स्पष्ट रूप से) FileParser ऑब्जेक्ट का संदर्भ रखते हुए भी हैं? –
इस बारे में बहुत परेशान नहीं है, बस एक अच्छा अनुस्मारक है कि यह तब तक हमेशा के लिए फिसलने जा रहा है जब तक कि फ़ाइलपार्स ऑब्जेक्ट जीवित रहता है। आप ParseFileFrobber को एक स्थिर विधि जोड़कर इसे "प्राकृतिक" बना सकते हैं। इसे नाम दें, एर्म, फ्रोब() या निरीक्षण करें()। कन्स्ट्रक्टर निजी बनाओ। –
मुझे आश्चर्य है कि आपको बनाए गए 'ParsedFileFrobber' उदाहरण की आवश्यकता क्यों नहीं है। जाहिर है कि कक्षा (और इसके रिश्तेदार 'पार्सडफाइल *') एक निश्चित स्थिति का उत्पादन करने वाले ईवेंट हैंडलर में कुछ कर रहे हैं। वह राज्य कहां रखा जाता है? हम जो जानते हैं उससे, यह 'पार्सडफाइलफ्रबर' के अंदर होना चाहिए। और अगर हम उस राज्य में रूचि रखते हैं (मुझे लगता है कि हम हैं, अन्यथा, हम फाइल को बाद में क्यों पार्स करेंगे), हमें 'पार्सडफाइलफ्रबर' के उदाहरण तक पहुंचने की भी आवश्यकता होगी। मुझे लगता है कि हम तस्वीर का केवल एक हिस्सा देख रहे हैं, न कि पूरी चीज यहां। –