2011-12-05 11 views
7

मेरे पास कोड अनुबंधों के संबंध में कई प्रश्न हैं, और उनके उपयोग के लिए सर्वोत्तम अभ्यास हैं। कहते हैं कि चलो हम एक वर्ग है, कई गुणों के साथ है (उदाहरण के लिए नीचे देखें):कोड अनुबंध सर्वोत्तम अभ्यास

class Class1 
{ 
    // Fields 
    private string _property1;  //Required for usage 
    private List<object> _property2; //Not required for usage 

    // Properties 
    public string Property1 
    { 
     get 
     { 
      return this._property1; 
     }    
     set 
     { 
      Contract.Requires(value != null); 
      this._property1 = value; 
     } 
    } 
    public List<object> Property2 
    { 
     get 
     { 
      return this._property2; 
     } 
     set 
     { 
      Contract.Requires(value != null); 
      this._property2 = value; 
     } 
    } 

    public Class1(string property1, List<object> property2) 
    { 
     Contract.Requires(property1 != null); 
     Contract.Requires(property2 != null); 

     this.Property1 = property1; 
     this.Property2 = property2; 
    } 

    public Class1(string property1) 
     : this(property1, new List<object>()) 
    { } 
} 

कुछ स्पष्टीकरण मैं क्या हासिल करना चाहते के बारे में:

(क) property1 एक आवश्यक फ़ील्ड है। वस्तु 2 के सामान्य उपयोग के लिए संपत्ति 2 स्पष्ट रूप से आवश्यक नहीं है।

मैं निम्नलिखित प्रश्न हैं:

  1. मैं भी property2 के लिए अनुबंध से परेशान करना चाहिए; क्योंकि property2 एक आवश्यक फ़ील्ड नहीं है, क्या इसका अनुबंध होना चाहिए। संपत्ति 2 पर अनुबंध रखने से संकेत मिलता है कि यह वास्तव में वस्तु के सामान्य उपयोग के लिए आवश्यक है;

  2. हालांकि property2 स्पष्ट रूप से की आवश्यकता नहीं है, वहाँ यह शून्य होने के लिए कोई संभावित कारण यह है सेटर पर इस प्रकार परिभाषित किया गया अनुबंध है। संपत्ति 2 पर अनुबंध को परिभाषित नहीं करना कॉलिंग कोड में शून्य जांच को कम करेगा? यह बग को कम करना चाहिए और कोड की रखरखाव में सुधार करना चाहिए - क्या यह धारणा सही है?

  3. यदि यह सही है, मैं कैसे कोड है कि property2 अशक्त कभी नहीं होगा बुला कर यह सुनिश्चित करते हैं? क्या मैं Contract.Invariant (property2! = Null) का उपयोग करता हूं; या अनुबंध.इन्चर (प्रॉपर्टी 2! = नल) कन्स्ट्रक्टर, या कॉन्ट्रैक्ट। इंश्योरेंस (प्रॉपर्टी 2! = नल) इनिट(), या कॉन्ट्रैक्ट में। एंटर (प्रॉपर्टी! = नल) सेटर में? (यानी अगर अनुबंध.इन्सर्स (property2! = null) का उपयोग करते हैं, तो यह कहां रखा जाता है)?

मेरी माफी माँगती है अगर प्रश्न सरल लगते हैं। मैं सिर्फ इस मामले पर विचारों की तलाश में हूं, और आप जो लोग सबसे अच्छा अभ्यास मानते हैं।

+0

मैं कारणों से आप सूचीबद्ध के लिए संपत्ति 2 पर अनुबंध के साथ सहमत हैं। –

उत्तर

3

यह है कि मैं क्या संविदा के रूप में जहाँ तक की सिफारिश करेंगे है:

class Class1 
    { 
     // Fields 
     private string _property1;  //Required for usage 
     private List<object> _property2; //Not required for usage 

     // Properties 
     public string Property1 
     { 
      get 
      { 
       Contract.Ensures(Contract.Result<string>() != null); 
       return this._property1; 
      } 
      set 
      { 
       Contract.Requires(value != null); 
       this._property1 = value; 
      } 
     } 

     public List<object> Property2 
     { 
      get 
      { 
       Contract.Ensures(Contract.Result<List<object>>() != null); 
       return this._property2; 
      } 
      set 
      { 
       Contract.Requires(value != null); 
       this._property2 = value; 
      } 
     } 

     public Class1(string property1, List<object> property2) 
     { 
      Contract.Requires(property1 != null); 
      Contract.Requires(property2 != null); 

      this.Property1 = property1; 
      this.Property2 = property2; 
     } 

     public Class1(string property1) 
      : this(property1, new List<object>()) 
     { 
      Contract.Requires(property1 != null); 
     } 

     [ContractInvariantMethod] 
     private void ContractInvariants() 
     { 
      Contract.Invariant(_property1 != null); 
      Contract.Invariant(_property2 != null); 
     } 
    } 

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

+0

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

2

मुझे लगता है कि यहाँ में निजी पसंद का एक बहुत है, लेकिन मेरी 2 सेंट ...

1) मैं करूंगा, और संभवतः एक वैकल्पिक तर्क के रूप में property2 के लिए निर्माताओं को समायोजित करने के लिए परीक्षा होगी:

Class1(string property1, List<object> property2 = new List<object>())  
{  
    Contract.Requires(property1 != null);  
    Contract.Requires(property2 != null);  

    this.Property1 = property1;  
    this.Property2 = property2;  
} 

2) 3

3) इससे पहले कि मैं कोड बुला में अशक्त चेकों को कम करने में खुशी होगी, मैं व्यक्तिगत रूप से एक

Contract.Ensures(property2 != null) 
देखने के लिए पसंद करेंगे देखें

गेटर पर - मैं VS11 सीटीपी देखा है परिभाषाओं तो यह मैं तो पता होगा मैं nulls के लिए जाँच करने की जरूरत नहीं है देखने के लिए सक्षम होने के लिए टूलटिप्स में ठेके को दर्शाता है। मैं सेटर पर Requires रखूंगा।

+0

उत्कृष्ट। धन्यवाद –

1

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

class Class1 
{ 
    // Fields 
    private string _property1;  //Required for usage 
    private List<object> _property2 = new List<object>(); //Not required for usage 

    // Properties 
    public string Property1 
    { 
     get 
     { 
      return this._property1; 
     }    
     set 
     { 
      Contract.Requires(value != null); 
      this._property1 = value; 
     } 
    } 
    public List<object> Property2 
    { 
     get 
     { 
      return this._property2; 
     } 
     //We don't have a setter. 
    } 

    public Class1(string property1) 
    { 
     Contract.Requires(property1 != null); 

     this.Property1 = property1; 
    } 
} 
+0

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

+0

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

1

1/2: संपत्ति 2 पर अनुबंध होने के लिए उपयुक्त है यदि वह व्यवहार है जिसे आप लागू करना चाहते हैं यानी यह शून्य नहीं होना चाहिए, और निश्चित रूप से शून्य जांच और नल के आसपास संभावित बग की आवश्यकता को कम कर देगा।

3: इस सवाल का मैं अपने वर्ग के रूप में

class Class1 
{ 
    //Properties 
    public string Property1 { get; set; } 
    public List<object> Property2 { get; set; } 

    public Class1(string property1, List<object> property2) 
    { 
     Contract.Requires(property1 != null); 
     Contract.Requires(property2 != null); 

     Property1 = property1; 
     Property2 = property2; 
    } 

    public Class1(string property1) 
     : this(property1, new List<object>()) 
    { 
     Contract.Requires(property1 != null); 
    } 

    [ContractInvariantMethod] 
    private void ObjectInvariant() 
    { 
     Contract.Invariant(Property1 != null); 
     Contract.Invariant(Property2 != null); 
    } 
} 

इस प्रकार आप अपनी कक्षा में ऑटो कार्यान्वित गुण आप Contract.Invariant() उपयोग कर सकते हैं जब फिर से लिखा है जवाब देने के लिए। यह आपकी संपत्ति में अनावश्यक अनुबंध बनाता है इसलिए अब निम्न कोड की आवश्यकता नहीं है।

public string Property1 
{ 
    get 
    { 
     Contract.Ensures(Contract.Result<string>() != null); 
     return this._property1; 
    }    
    set 
    { 
     Contract.Requires(value != null); 
     this._property1 = value; 
    } 
} 

यह संपत्ति सुरक्षा का ख्याल रखेगा। पूरी तरह से यह सुनिश्चित करने के लिए कि संपत्ति कभी भी शून्य नहीं होगी, फिर आप एक अनुबंध जोड़ देंगे। निर्माता (संपत्ति 1! = शून्य) निर्माता में।

मुझे पता है कि यह उत्तर 3 साल देर से है, लेकिन यह आपके लिए कुछ उपयोग हो सकता है!

स्रोत: http://research.microsoft.com/en-us/projects/contracts/userdoc.pdf