2011-06-01 21 views
8

मेरे पास DatabaseRow नामक एक अमूर्त वर्ग है जिसे, व्युत्पन्न और निर्माण के बाद, मुख्य रूप से Load(object id) विधि से लोड किया जाता है।विधि चेनिंग के लिए सर्वोत्तम अभ्यास ("इसे वापस करें")

मेरे पास बहुत सारे कोड हैं जो कक्षा का एक नया उदाहरण बनाता है, इसे आईडी से लोड करता है, फिर कक्षा लौटाता है। मैं इस कोड को कोड की एक पंक्ति में सरल बनाना चाहता हूं (बस साफ रहना, वहां बहुत सारे वर्ग हैं जिनमें केवल उन गुणों की सूचियां होंगी जो इन लोड किए गए उदाहरणों को वापस कर दें)।

ऐसा करने के दो तरीके हैं जो मैं कर सकता हूं, लेकिन न तो मुझे 'सही' लगता है।

1. मैं अपने Load विधि के अंत में कर सकते थे return this; और return new Derived().Load(id);

2. का उपयोग मैं एक लोड विधि वापस जाने के लिए एक सामान्य विधि बना सकते हैं।

public static T LoadRow<T>(object id) where T : DatabaseRow, new() 
{ 
    T row = new T(); 
    row.Load(id); 
    return row; 
} 

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

क्या किसी को भी अन्य समाधानों के बारे में पता है जो इन दोनों से बेहतर हो सकते हैं?

समाधान:

SirViver के जवाब और टिप्पणी पढ़ने के बाद, मुझे एहसास हुआ कि सभी गुण लौटे जरूरत जा रहा है वैसे भी कैश हो जाने की। समाधान दृष्टि से अलग था, लेकिन विकल्प (जैसा कि मैं किसी भी व्यक्ति को इस जवाब के साथ आने की उम्मीद नहीं करता क्योंकि मैंने डिजाइन के इस हिस्से को समझाया नहीं है)

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

private Dictionary<string, DatabaseRow> linkedRows; 

    protected T GetLinkedRow<T>(string key) where T : DatabaseRow, new() 
    { 
     if (linkedRows.ContainsKey(key)) return (T)linkedRows[key]; 
     else 
     { 
      T row = new T(); 
      row.Load(this[key]); 
      linkedRows.Add(key, row); 
      return row; 
     } 
    } 

उत्तर

3

व्यक्तिगत रूप से, मुझे लगता है कि यह श्रृंखला विधि कॉल वस्तु दृष्टान्त पर वास्तविक sideffects है कि करने के लिए बुरा व्यवहार है। ईमानदार होने के लिए, मुझे लगता है कि दोनों उदाहरण काफी बदसूरत "हैक्स" हैं जिनका एकमात्र उद्देश्य कोड की दो पंक्तियों को बचा रहा है। मुझे नहीं लगता कि नतीजा वास्तव में और अधिक पठनीय है।

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

+0

मेरे मामले में, मेरे पास एक वर्ग है जो 'डाटाबेसरो' प्राप्त करता है, और इसमें 5 गुण होते हैं जो सभी एक ही फ़ंक्शन का उपयोग करते हैं। कोड की 5 लाइनें होने के कारण, 'सार्वजनिक व्युत्पन्न MyProperty के समान {{वापसी नया व्युत्पन्न()। लोड (myInt); }} गुणों को बहु-लाइन कोड में अलग करने से अधिक neater होगा। – Connell

+0

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

+0

यह बात है !!! मुझे अब इतनी बेवकूफ लगती है। कैशिंग पर आपकी टिप्पणी ने मुझे याद दिलाया कि मैंने पहले ही इस डेटाबेस को अपने डेटाबेसरॉव क्लास के नीचे बनाया है! 'संरक्षित टी GetLinkedRow (स्ट्रिंग कुंजी) जहां टी: डाटाबेसरो, नया()' पंक्ति को लोड करता है और इसे 'कुंजी' के मान के आधार पर एक शब्दकोश में कैश करता है। – Connell

2

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

व्यक्तिगत रूप से मैं नंबर 2 जैसे समाधानों के शौकीन नहीं हूं, क्योंकि इसे "एक जिम्मेदारी" सिद्धांत का उल्लंघन करने के लिए कहा जा सकता है।

0

हालांकि मैं व्यक्तिगत रूप से this लौटने के तरीकों को पसंद करता हूं क्योंकि यह उन्हें जंजीर होने की अनुमति देता है, मुझे लगता है कि .NET ढांचे (लिंक तक) तक, यह डूब गया था। दिमाग में आने का कारण यह है:

तरीके या तो परिणाम लौटाते हैं या ऑब्जेक्ट की स्थिति बदलते हैं।रिटर्निंग this दोनों का थोड़ा सा है: ऑब्जेक्ट की स्थिति बदलना और फिर "परिणाम" लौटना - सिवाय इसके कि परिणाम संशोधित मूल वस्तु है। यह उपयोगकर्ता की अपेक्षाओं को फिट नहीं करता है।

के बारे में क्या:

public class Derived : DatabaseRow 
{ 
    public Derived(object id): 
    { 
     Load(id); 
    } 
} 

और इस तरह इसका इस्तेमाल:

return new Derived(id); 
+0

मैं यहां आपके दूसरे पैराग्राफ से अधिक सहमत नहीं हो सका। मैं वास्तव में मूल रूप से आपके समाधान के समान कुछ उपयोग कर रहा था, हालांकि मैंने इसके खिलाफ फैसला किया और लोड विधि में बदल दिया क्योंकि मुझे नहीं लगता कि रचनाकारों के पास इतना कार्यक्षमता होनी चाहिए (इस मामले में, SQL क्वेरी निष्पादित करना) – Connell

+0

@ कॉनेल वॉकिन्स: मेरे पास है अपने आप से पहले रचनाकारों के बारे में सोचा, लेकिन अब उन्हें एक गारंटी के रूप में सोचना है कि वस्तु एक उपयोगी राज्य में है। इसलिए, यदि लोड विधि को कॉल करने के बाद ऑब्जेक्ट का उपयोग कभी भी किया जाता है, तो आप वास्तव में इसे निर्माता में डाल सकते हैं! –

1

विकल्प 1 केवल स्वीकार्य है यदि लोड किए बिना पंक्ति हो सकती है। यह आपको ऐसा करने की अनुमति देने वाले पैटर्न के कारण है:

return new Derived(); 

व्यक्तिगत रूप से मैं स्थैतिक विधि पसंद करूंगा। लेकिन मुझे संदेह है कि यह सिर्फ व्यक्तिगत वरीयता का मामला है।

जैसा कि एसएसएस कहता है कि दूसरा विकल्प (इसे विकल्प 3 कहता है) को व्युत्पन्न में कन्स्ट्रक्टर को अधिभारित करना है जो काम भी करेगा, हालांकि कई रचनाकार अक्सर भ्रमित हो सकते हैं क्योंकि कॉलिंग कोड में कुछ भी नहीं है जो वर्णन करता है क्या हो रहा है।

विकल्प 1:

return new Derived().Load(10); 

विकल्प 2:

return Derived.Load(10); 

विकल्प 3:

return new Derived(10); 

विकल्प 1 लगता है कि आपके द्वारा बनाए गए ज़रूरत से ज़्यादा वस्तु हो रही है। विकल्प 2 अच्छा है क्योंकि ऐसा लगता है कि यह ऐसा कर रहा है। विकल्प 3 यह क्या करता है इसके बारे में भ्रम छोड़ देता है।

+0

कक्षा बनाना और इसे लोड करना काफी संभव है। यदि आप डेटाबेस में एक नई पंक्ति बना रहे थे, तो आप एक नया उदाहरण बनायेंगे, गुण भरें और फिर 'सहेजें()' विधि को कॉल करें। क्या आपका मतलब सामान्य स्थैतिक विधि है? या प्रत्येक व्युत्पन्न कक्षा में एक स्थिर विधि? – Connell

+0

आह, मैंने अभी आपका संपादन देखा है। विकल्प 2 सही दिखता है, लेकिन इसके साथ बात यह है कि मुझे इस प्रकार के हर व्युत्पन्न वर्ग के लिए एक ही स्थिर विधि बनाने की आवश्यकता होगी, जो अनावश्यक प्रतीत होता है। – Connell

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