2011-12-15 11 views
8

लागू करते समय कन्स्ट्रक्टर में अपवादों से निपटना मैंने पढ़ा है कि मुझे IDisposable लागू करने की आवश्यकता है यदि मेरी कक्षा में सदस्य चर है जो स्वयं ही IDISposable है। ठीक है, मैं IDisposable इंटरफेस को लागू कर रहा हूँ क्योंकि मेरी कक्षा एक डेटाबेस वस्तु (नीचे db वर्ग के सदस्य) शामिल हैं जो IDisposable ही है:IDISposable

public class CommissionModel : IDisposable 
    { 
     protected PetaPoco.Database db; 

     public CommissionModel() 
     { 
      string connectionString = "Server=localhost;..."; 

      // The line below may throw an exception (!!!) 
      db = new PetaPoco.Database(connectionString, "mysql");    
     } 

     // Automatically close database connection 
     public void Dispose() 
     { 
      if (db != null) 
       db.Dispose(); 

      db = null; 
     } 

     public void InsertRecord(Record somerecord) 
     { 
      // ... 
      db.Insert(somerecord); 
     } 

समस्या db सदस्य की इन्स्टेन्शियशन कुछ परिस्थितियों में विफल हो सकता है है। जब अपवाद निर्माता में फेंक दिया जाता है और डेटाबेस वस्तु नहीं बनाया जाता है मुझे क्या करना चाहिए? मैं अपवाद rethrow चाहिए या हो सकता है InsertRecord विधि में अगर db != null जाँच?

+0

आईएमओ आपको अपवाद को फिर से करना चाहिए। बेहतर परत अलगाव के लिए, आप कुछ उच्च स्तर पर मूल निष्पादन को लपेट सकते हैं। यह सूचित करना बेहतर है कि कुछ गलत हो रहा है। – Krzysztof

+0

पर एक नजर डालें [ठोस] (https://en.wikipedia.org/wiki/Solid_%28object-oriented_design%29), विशेष रूप से पर [SRP] (https://en.wikipedia.org/wiki/Single_responsibility_principle) और [DI] (https://en.wikipedia.org/wiki/Dependency_inversion_principle) – oleksii

उत्तर

1

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

मेरा सुझाव है कि आप अपना कोड छोड़ दें और वैश्विक स्थान पर अपवादों को संभालें जैसे ग्लोबल.एक्सएक्स में एप्लिकेशन_इरर ईवेंट या आयोग मॉडल शुरू करने वाली घटना।

2

आदर्श रूप से आपको कन्स्ट्रक्टर में कोई भी "काम" नहीं करना चाहिए। कन्स्ट्रक्टर में काम वास्तव में ऑब्जेक्ट संदर्भों को जोड़ना चाहिए। यह आपको इसके बजाय नकली कक्षाओं को जोड़कर इस वर्ग का परीक्षण करने की अनुमति देगा।

ऐसा करें:

public CommissionModel(PetaPoco.Database db) { 
    this.db = db; 
} 
+1

+1 यह सबसे अच्छा जवाब है जो ओपी को बेहतर डिज़ाइन की ओर इंगित करता है। मैं सोलिड सिद्धांतों का भी उल्लेख करता हूं और शायद 'पेटापोको। डाटाबेस' – oleksii

+0

@oleksii के बजाय 'आईडीबेसैट' का उपयोग करता हूं, मुझे उस पर आपसे असहमत होना पड़ता है। 'आयोग मॉडल 'के कार्यान्वयन के पीछे कारण कोड के अन्य हिस्सों से सभी निम्न स्तर के डेटा मैनिपुलेशन और डेटाबेस हैंडलिंग कार्यक्षमता को अलग करना है। इसके अलावा, एक दिन मैं पेटापोको के बजाय एक और ओआरएम ढांचे पर स्विच करने का फैसला कर सकता हूं। – ezpresso

+0

@ezpresso * "[...] एक दिन मैं पेटापोको के बजाय एक और ओआरएम ढांचे पर स्विच करने का फैसला कर सकता हूं" * यही कारण है कि आपको एक इंटरफ़ेस पास करने की आवश्यकता हो सकती है, जिसे अब पेटापोको के साथ कार्यान्वित किया जाना है, और बाद में, आप चाहते हैं, आप अन्य ओआरएम में बदल सकते हैं। मुझे यकीन नहीं है कि मैं आपके साथ इस बात का अनुपालन करता हूं कि आप किस विशेष चीज़ से असहमत हैं। क्या आप इसे मुझे समझा सकते हैं? – oleksii

3

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

मैं आमतौर पर एक ऑपरेशन को आगे बढ़ाने की अनुशंसा करता हूं जो बाहरी परिस्थितियों (और अमान्य पैरामीटर मान की तरह नहीं) के कारण "कनेक्ट" जैसी अलग विधि के कारण विफल हो सकता है।

2

ऐसा लगता है कि आप कुछ भी करने को नहीं है।

यदि आपकी निर्माण प्रक्रिया बाधित है संसाधन संसाधन नहीं बनाया गया है। अधिकांश उपयोग परिदृश्यों में (यह आपकी कक्षा के बाहर रहता है), निपटान() कभी नहीं कहा जाएगा। लेकिन यहां तक ​​कि जब भी, आपका if (db != null) कोड पर्याप्त है।

कुछ मामूली अंक:

  • निपटान के अंदर db = null;() व्यर्थ है।
  • InsertRecord() जाँच if (db != null)
1

द्वारा शुरू कर देना चाहिए अगर वहाँ कोई रास्ता नहीं है कि एक अपवाद हो सकता है (*) समय निर्माता एक संसाधन और समय आवेदन के लिए वापस आ जाता है प्राप्त कर लेता है के बीच है, चिंता की बात नहीं है के बारे में।

तो यह संभव है की तुलना में एक अपवाद ऐसे हालात में हो सकता है, मैं की तरह एक पैटर्न सुझाव है:

 
public class CommissionModel : IDisposable 
    { 
     protected PetaPoco.Database db; 
     protected OtherResourceType resource2; 

     public CommissionModel() 
     { 
      Boolean ok; 
      string connectionString = "Server=localhost;..."; 

      ok = false; 
      try 
      { 
       // Either of the next two lines may throw an exception 
       db = new PetaPoco.Database(connectionString, "mysql"); 
       resource2 = new OtherResourceType(); 
       // Once we make it this far, we should be successful 
       ok = true; 
      } 
      finally 
      { 
       if (!ok) 
        Dispose(); 
      } 
     } 

     // Automatically close database connection 
     public void Dispose() 
     { 
      Zap(ref db); // Method to Dispose and null out, only if not null 
      Zap(ref resource2); 
     } 
    } 

(*) यह लगभग हमेशा संभव है एक ThreadAbortException होने के लिए अगर कुछ मतलब बुरा राक्षस कॉल पर चलने। अपने कोड पर निरस्त करें, लेकिन किसी भी मामले में इसके बारे में वास्तव में कुछ भी नहीं किया जाना है।

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