वास्तव में C#में CodeContracts को पसंद करने की कोशिश कर रहा है




code-contracts (4)

मैं अंत में .NET 3.5 / 4.0 चौखटे में जोड़े गए सभी नए के साथ कैचअप खेल रहा हूं। पिछले कुछ दिनों से मैं कोडकॉन्ट्रैक्ट्स के साथ काम कर रहा हूं और मैं वास्तव में उन्हें पसंद करने की कोशिश कर रहा हूं। मैं उत्सुक हूं कि अन्य लोग C # में CodeContracts के कार्यान्वयन के बारे में क्या सोचते हैं? विशेष रूप से, कैसे लोग इंटरफेस के लिए कॉन्ट्रैक्ट क्लासेस, कॉन्ट्रैक्ट इनवियर्स के लिए कॉन्ट्रैक्ट मेथड्स आदि चीजों को व्यवस्थित कर रहे हैं?

मुझे वह मान्यता पसंद है जो अनुबंध प्रदान करता है, पहली नज़र में वे बहुत अच्छे लगते हैं। कुछ सरल लाइनों के साथ मैं अपना कोड चलाने से पहले कुछ अच्छी बिल्ड चेकिंग प्राप्त कर सकता हूं। दुर्भाग्य से, मुझे यह महसूस करने में कठिन समय हो रहा है कि जिस तरह से कोड कॉन्ट्रैक्ट को C # में लागू किया गया है, वे मेरे कोड को क्लर्क कर रहे हैं, जितना वे कॉन्ट्रैक्ट कर रहे हैं। और अनुबंधों का पूरा लाभ उठाने के लिए, मैं अपने कोड को मान्यताओं और दावे आदि के साथ जोड़ रहा हूं (जो मुझे पता है कि कुछ कहेंगे यह अच्छी बात है); लेकिन जैसा कि नीचे दिए गए मेरे कुछ उदाहरणों से पता चलेगा, यह 4 या 5 लाइनों में एक एकल सरल रेखा को बदल देता है, और वास्तव में वैकल्पिक दृष्टिकोणों (यानी, जोर, अपवाद आदि) के बारे में मेरी राय में पर्याप्त मूल्य नहीं जोड़ता है।

वर्तमान में, मेरी सबसे बड़ी निराशा हैं:

इंटरफ़ेस अनुबंध:

[ContractClass(typeof(IInterfaceContract))]
  public interface IInterface
  {
    Object Method(Object arg);
  }

  [ContractClassFor(typeof(IInterface))]
  internal abstract class IInterfaceContract
  {
    private IInterfaceContract() { }

    Object IInterface.Method(Object arg)
    {
      Contract.Requires(arg != null);
      Contract.Ensures(Contract.Result<Object>() != null);
      return default(Object);
    }
  }

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

कोड ब्लोट:

typeof(Action<>).MakeGenericType(typeof(Object);

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

var genericAction = typeof(Action<>);

Contract.Assume(genericAction.IsGenericType);
Contract.Assume(genericAction.GetGenericArguments().Length == 1);

genericAction.MakeGenericType(typeof(Object));

बस चीजों को प्रलेखित रखने के लिए (हाँ मुझे पता है कि मैं एक विधि / वर्ग आदि के लिए इसे बंद करने के लिए ContractVerificationAttribute का उपयोग कर सकता हूं, या विशेष संदेशों को लक्षित करने के लिए SuppressMessageAttribbute कर सकता हूं, लेकिन यह उद्देश्य को हराने के लिए लगता है क्योंकि यह कोड जल्दी से शमन आदि से अटे पड़े हो जाएगा)

इसके अलावा, एक मामले की तरह ले रहा है

  public class MyClass
    : IInterface
  {
    private readonly Object _obj;

    public Object Property
    {
      get
      {
        Contract.Ensures(Contract.Result<Object>() != null);
        return _obj;
      }
    }

    public MyClass(Object obj)
    {
      Contract.Requires(obj != null);

      _obj = obj;
    }
  }

obj को शून्य होने की आवश्यकता नहीं है, और एक पठनीय क्षेत्र पर सेट किया जाता है जिसे बदला नहीं जा सकता है, फिर भी मुझे अभी भी अपनी कक्षा में एक "मार्कअप" विधि जोड़ने की आवश्यकता है ताकि null नहीं होने के लिए मेरी संपत्ति की आवश्यकता को सिद्ध किया जा सके:

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

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

धन्यवाद!


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

CC टीम ने कहा है कि Attributes का उपयोग करना केवल इतना शक्तिशाली नहीं है, क्योंकि आप उनमें लैम्ब्डा जैसी चीजों को शामिल नहीं कर सकते हैं। वे [NotNull] जैसी चीजों को शामिल कर सकते हैं, लेकिन ऐसा नहीं करने के लिए चुना है क्योंकि वे सीसी को यथासंभव सामान्य रखने की कोशिश कर रहे हैं।

एक कारण यह है कि CC एक लाइब्रेरी है (एक विस्तारित C ​​# के भाग के बजाय) यह है कि यह सभी .NET भाषाओं में समर्थित है।

आप टीम के तर्क के बारे में अधिक here पढ़ सकते हैं।

वास्तव में इसका उपयोग करने के संदर्भ में, अब तक मैं अपने इंटरफ़ेस कॉन्ट्रैक्ट्स को इंटरफ़ेस के समान फ़ाइल में रख रहा हूं, जिसका अर्थ है कि यह सभी एक ही स्थान पर प्रलेखित है। यह कुछ ऐसा है जिस पर सुधार किया जाना चाहिए :)

कोड ब्लोट [...]

आपकी दूसरी शिकायत शायद कुछ है जिसे लागू किया जा सकता है - मैं सुझाव दूंगा कि इसे कोड कॉन्ट्रैक्ट फोरम पर पोस्ट किया जाए। (संपादित करें: लगता है कि किसी के पास पहले से ही है , लेकिन अभी तक कोई जवाब नहीं है।)

हालांकि, यह हमेशा मामला होगा कि अंडर-निर्दिष्ट अनुबंधों को उनके आसपास अधिक मान्यताओं की आवश्यकता होगी। यदि आप .NET फ्रेमवर्क में इस तरह के मामले में भाग लेते हैं, तो आप अनुरोध कर सकते हैं कि लाइब्रेरीज़ थ्रेड पर गुम अनुबंध में अनुबंध जोड़े जा सकते हैं।

इसके अलावा, एक मामले की तरह […]

इस पर ध्यान दिया गया है । यदि आपके पास एक ऑटो-प्रॉपर्टी है, तो आपको बस एक नॉन-नाल इनवेरिएंट जोड़ना होगा और प्री- / पोस्ट की शर्तों को उत्पन्न किया जाएगा:

public class MyClass : IInterface
{
    private Object Property { get; set; }

    [ContractInvariantMethod]
    private void Invariants()
    {
        Contract.Invariant(Property != null);
    }
}

आप शायद अपनी कक्षाओं के लिए वैसे भी अन्य आक्रमणकारियों के साथ समाप्त हो जाएंगे, इसलिए यह इतना बड़ा सौदा नहीं है।


मैं वास्तव में इसे भी पसंद करना चाहता था, और एक नई परियोजना में एक कार्यान्वयन के साथ काफी दूर चला गया, जब तक कि मैंने इसके साथ छोटे छोटे मुद्दों पर भार नहीं उठाया।

मैं Microsoft के लिए Spec # को पुनर्जीवित करना पसंद करूंगा। मुझे पता है कि कोड अनुबंध भाषा के रूप में उपलब्ध होने के लिए एक पुस्तकालय के रूप में लिखा गया था, लेकिन यहां तक ​​कि संकलक विश्लेषण की गति संकलक समर्थन के लिए रोती है।

यह आदमी कुछ ऐसे ही बिंदु उठाता है: http://earthli.com/news/view_article.php?id=2183

वैसे भी, कोई भी एक समस्या नहीं थी जो एक डील-ब्रेकर थी, लेकिन चिढ़ का एक संचय:

  • स्थैतिक विश्लेषण बहुत धीमा है। आप इसे पृष्ठभूमि में चलाने के लिए सेट कर सकते हैं, लेकिन फिर इसे अनदेखा करना बहुत आसान है।
  • उदाहरण के लिए स्थैतिक विश्लेषण महान नहीं है:
    • यह केवल सरल नियंत्रण प्रवाह को संभालता है
    • यह नहीं मानेंगे कि आसानी से खेतों में अपरिवर्तनीय हैं
    • संग्रह स्थैतिक चेकर (केवल रनटाइम) द्वारा नियंत्रित नहीं किया जाता है
  • कोई प्रतिनिधि अनुबंध नहीं करता है
  • जब तक आप सक्रिय रूप से resharper चेतावनियों को एक तरह से या किसी अन्य तरीके से नहीं दबाते हैं, तब तक रिचार्पर के साथ अच्छा काम नहीं करता है
    • रेस्परर आशावादी है। यह मान लेंगे कि एक विधि पैरामीटर अशक्त नहीं है, जब तक कि आप इसे संकेत नहीं देते हैं कि यह हो सकता है - Contract.Assume(thing != null) तरह। Contract.Assume(thing != null)
  • कभी-कभी अस्पष्ट स्रोत से उपजी कई चेतावनी और सुझाव उत्पन्न कर सकते हैं।
    • जिस समय टीम का कोई भी सदस्य अपना ध्यान हटाता है, चेतावनियों की संख्या हर किसी के लिए भारी हो जाती है
  • इंटरफेस के लिए अमूर्त अनुबंध वर्गों को निर्दिष्ट करने की आवश्यकता दर्द है।
  • रनटाइम अनुबंध आईएल पुनर्लेखन का उपयोग करते हैं, जो स्पष्ट रूप से पोस्टशार्प जैसे अन्य पुनर्लेखन समाधानों के साथ अच्छा नहीं खेलता है (मुझे लगता है।
    • आईएल पुनर्लेखन के परिणामस्वरूप, संपादन और जारी नहीं किया जा सकता है
  • अनुबंध liskov प्रतिस्थापन सिद्धांत को बहुत कसकर चिपकाते हैं: उपप्रकार कभी भी पूर्व-शर्तों को शिथिल नहीं कर सकते हैं। मेरा मतलब है, सिद्धांत रूप में अच्छा है, लेकिन मुझे लगता है कि यह एक दर्द होगा जब ओवर-अनुबंधित 3 पार्टी कोड के साथ काम करना।

यदि आपके कोड ब्लोट के बारे में चिंतित हैं, तो मैं आपको एक विकल्प के रूप में पहलू ओरिएंटेड प्रोग्रामिंग को देखने के लिए प्रोत्साहित करूंगा।

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

दुर्भाग्य से C # में AOP का समर्थन बहुत अच्छा नहीं है, लेकिन इस कार्यक्षमता को जोड़ने वाले कुछ पुस्तकालय हैं।

और जैसा कि मैंने अन्य C # कार्यान्वयन के प्रति भी ऐसा ही महसूस किया है जैसा कि आपने अनुबंधों के साथ पाया है यह सब पहली बार में ठीक लगता है जब तक आप हुड को उठाते हैं और एक गंभीर फैशन में इसका उपयोग करना शुरू करते हैं।


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

आपको ऑब्जेक्ट इनवाइट जोड़ने की आवश्यकता क्यों है? आपको केवल उतना ही जोड़ना है जितना आप आवश्यक महसूस करते हैं।

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





code-contracts