एक विधि को चिह्नित करने के लिए सबसे अच्छा अभ्यास जो प्रतिबिंब के माध्यम से कहा जाता है?


11

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

परावर्तन के माध्यम से बुलाए जाने के लिए हमें किस तरह से चिह्नित / दस्तावेज़ विधियों का उपयोग करना चाहिए?

आदर्श रूप से, विधि को इस तरह से चिह्नित किया जाना चाहिए कि दोनों सहकर्मियों और विज़ुअल स्टूडियो / रोसलिन और अन्य स्वचालित उपकरण 'देखें' कि विधि को प्रतिबिंब के माध्यम से बुलाया जाना है।

मुझे दो विकल्पों का पता है जिनका हम उपयोग कर सकते हैं लेकिन दोनों ही काफी संतोषजनक नहीं हैं। चूंकि विज़ुअल स्टूडियो को संदर्भ नहीं मिल सकते हैं:

  • कस्टम विशेषता का उपयोग करें और इस विशेषता के साथ निर्माता को चिह्नित करें।
    • एक समस्या यह है कि गुण गुण एक विधि संदर्भ नहीं हो सकते हैं, इसलिए निर्माणकर्ता अभी भी 0 संदर्भ होने के रूप में दिखाएगा।
    • कस्टम विशेषता से परिचित सहकर्मी संभवतः इसकी उपेक्षा नहीं करेंगे।
    • मेरे वर्तमान दृष्टिकोण का एक लाभ यह है कि प्रतिबिंब भाग को कॉल करने वाले निर्माता को खोजने के लिए विशेषता का उपयोग कर सकता है।
  • दस्तावेज़ के लिए टिप्पणियों का उपयोग करें कि एक विधि / निर्माता को प्रतिबिंब के माध्यम से बुलाया जाना है।
    • स्वचालित उपकरण टिप्पणियों को अनदेखा करते हैं (और सहकर्मी ऐसा भी कर सकते हैं)।
    • Xml प्रलेखन टिप्पणियाँ विजुअल स्टूडियो विधि / निर्माणकर्ता के लिए एक अतिरिक्त संदर्भ की गणना करने के लिए इस्तेमाल किया जा सकता है:
      चलो MyPluginवह वर्ग हो जिसका निर्माता प्रतिबिंब के माध्यम से आह्वान करता है। intपैरामीटर लेने वाले कंस्ट्रक्टरों के लिए इनवॉइसिंग प्रतिबिंब कोड खोजों को मान लें । निम्नलिखित प्रलेखन बनाता है कि कोड लेंस 1 संदर्भ वाले निर्माता को दिखाता है:
      /// <see cref="MyPlugin.MyPlugin(int)"/> is invoked via reflection

कौन से बेहतर विकल्प मौजूद हैं?
एक विधि / निर्माणकर्ता को चिह्नित करने के लिए सबसे अच्छा अभ्यास क्या है जिसे प्रतिबिंब के माध्यम से बुलाया जाना है?


बस स्पष्ट होने के लिए, यह किसी प्रकार के प्लगइन सिस्टम के लिए है, है ना?
whatsisname

2
आप मान रहे हैं कि आपके सहकर्मी आपकी हर बात को नज़रअंदाज़ करने या चूकने वाले हैं ... आप काम में इस तरह की अक्षमता से कोड को रोक नहीं सकते हैं। दस्तावेज़ीकरण मुझे आसान, स्वच्छ, सस्ता और उचित तरीका लगता है। अन्यथा घोषणात्मक प्रोग्रामिंग मौजूद नहीं होगी।
17

1
Resharper में [UsedImplictly] विशेषता है।
कोडइन्चोस

4
मुझे लगता है कि Xml डॉक्टर टिप्पणी विकल्प शायद आपका सबसे अच्छा विकल्प है। यह छोटा है, स्व-दस्तावेजीकरण है, और इसे किसी भी "हैक" या अतिरिक्त परिभाषा की आवश्यकता नहीं है।
डॉक ब्राउन

2
Xml प्रलेखन टिप्पणियों के लिए एक और वोट। यदि आप वैसे भी प्रलेखन बना रहे हैं, तो इसे जनरेट किए गए दस्तावेज़ में बाहर खड़ा होना चाहिए।
फ्रैंक हिलमैन

जवाबों:


12

सुझाए गए समाधानों का एक संयोजन:

  • XML डॉक्यूमेंटेशन टैग्स का उपयोग यह दस्तावेज करने के लिए करें कि कंस्ट्रक्टर / विधि प्रतिबिंब के माध्यम से कहा जाता है।
    यह सहकर्मियों (और मेरे भविष्य के स्वयं) के लिए इच्छित उपयोग को स्पष्ट करना चाहिए।
  • <see>कंस्ट्रक्टर / विधि के लिए संदर्भ गणना बढ़ाने के लिए -tag के माध्यम से 'ट्रिक' का उपयोग करें ।
    यह उस कोड लेंस को बनाता है और संदर्भों को दर्शाता है कि निर्माता / विधि संदर्भित है।
  • रेस्पर के साथ एनोटेट UsedImplicitlyAttribute
    • Resharper एक वास्तविक मानक है और [UsedImplicitly]इसमें ठीक से शब्दार्थ है।
    • Resharper का उपयोग नहीं करने वाले JetGrains ReSharper एनोटेशन को NuGet:
      PM> के जरिए इंस्टॉल कर सकते हैं Install-Package JetBrains.Annotations
  • यदि यह एक निजी विधि है और आप Visual Studio के कोड विश्लेषण का उपयोग कर रहे हैं, SupressMessageAttributeतो संदेश का उपयोग करें CA1811: Avoid uncalled private code

उदाहरण के लिए:

class MyPlugin
{
    /// <remarks>
    /// <see cref="MyPlugin.MyPlugin(int)"/> is called via reflection.
    /// </remarks>
    [JetBrains.Annotations.UsedImplicitly]
    public MyPlugin(int arg)
    {
        throw new NotImplementedException();
    }

    /// <remarks>
    /// <see cref="MyPlugin.MyPlugin(string)"/> is called via reflection.
    /// </remarks>
    [JetBrains.Annotations.UsedImplicitly]
    [System.Diagnostics.CodeAnalysis.SuppressMessage(
        "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode",
        Justification = "Constructor is called via reflection")]
    private MyPlugin(string arg)
    {
        throw new NotImplementedException();
    }
}

समाधान दोनों मानव पाठकों के लिए कंस्ट्रक्टर के इच्छित उपयोग और सी # और विज़ुअल स्टूडियो के साथ सबसे अधिक उपयोग किए जाने वाले 3 स्थिर कोड विश्लेषण प्रणालियों तक सीमित करता है।
नकारात्मक पक्ष यह है कि एक टिप्पणी और एक या दो एनोटेशन दोनों ही बेमानी लग सकते हैं।


नोट वहाँ भी है MeansImplicitUseAttributeकि एक UsedImplicitlyप्रभाव है कि अपनी विशेषताओं बनाने के लिए इस्तेमाल किया जा सकता है। यह सही स्थितियों में बहुत सारे विशेषता शोर को कम कर सकता है।
डेव कज़िन्यू

JetBrains का लिंक टूट गया है।
जॉन ज़ब्रोस्की

5

मैं एक .Net परियोजना में इस मुद्दे को कभी नहीं था, लेकिन मैं नियमित रूप से जावा परियोजनाओं के साथ एक ही मुद्दा है। मेरे सामान्य दृष्टिकोण में @SuppressWarnings("unused")टिप्पणी का उपयोग करते हुए एनोटेशन का उपयोग करना है, जिसमें बताया गया है कि (किसी भी चेतावनी को अक्षम करने का कारण दर्ज करना मेरे मानक कोड शैली का हिस्सा है - किसी भी समय कंपाइलर कुछ पता नहीं लगा सकता है, मुझे लगता है कि यह संभावना है कि एक मानव संघर्ष कर सकता है भी)। इससे स्थिर विश्लेषण साधनों को स्वचालित रूप से सुनिश्चित करने का लाभ मिलता है कि कोड को प्रत्यक्ष संदर्भ नहीं माना जाता है, और मानव पाठकों के लिए एक विस्तृत कारण दे रहा है।

जावा के C # समतुल्य @SuppressWarningsहै SuppressMessageAttribute। के लिए निजी तरीकों आप संदेश का उपयोग कर सकते CA1811: अनावश्यक निजी कोड से बचें ; उदाहरण के लिए:

class MyPlugin
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage(
        "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode",
        Justification = "Constructor is called via reflection")]
    private MyPlugin(int arg)
    {
        throw new NotImplementedException();
    }
}

(मुझे नहीं पता, लेकिन मान लें कि सीएलआई एक विशेषता का समर्थन करता है जो कि जावा के समान है जिसका मैं उल्लेख करता हूं; अगर किसी को पता है कि यह क्या है, कृपया मेरे उत्तर को इसके संदर्भ के रूप में संपादित करें ...)
जूल्स

stackoverflow.com/q/10926385/5934037 ऐसा लगता है।
Laiv

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

इसमें मौजूद है SuppressMessageAttribute( msdn.microsoft.com/en-us/library/… )। जो संदेश सबसे करीब आता है CA1811: Avoid uncalled private code( msdn.microsoft.com/en-us/library/ms182264.aspx ); मुझे अभी तक सार्वजनिक कोड के लिए एक संदेश नहीं मिला है।
कैस्पर वैन डेन बर्ग

2

दस्तावेज़ीकरण का एक विकल्प इकाई परीक्षण (एस) होगा जिससे यह सुनिश्चित हो सके कि प्रतिबिंब कॉल सफलतापूर्वक चले।

इस तरह अगर कोई आपके निर्माण / परीक्षण प्रक्रिया के तरीकों को बदलता है या हटाता है, तो आपको सचेत करना चाहिए कि आपने कुछ तोड़ दिया है।


0

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


यह सच है कि आमतौर पर विरासत का रास्ता यही होगा। और कक्षाएं वास्तव में वंशानुक्रम से संबंधित हैं। लेकिन विरासत से परे एक नई मिसाल कायम करना। इसके अलावा, मैं स्थैतिक विधियों के 'वंशानुक्रम' पर निर्भर हूं, और चूंकि C # वर्ग स्लॉट का समर्थन नहीं करता है; चारों ओर एक रास्ता है, जो मैं उपयोग करता हूं, लेकिन यह इस टिप्पणी के दायरे से परे है।
कैस्पर वैन डेन बर्ग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.