सी # पैटर्न को "फ्री फ़ंक्शंस" को संभालने के लिए, हेल्पर-स्टाइल "यूटिलिटी बैग" स्टैटिक क्लासेस से बचें


9

मैं हाल ही में कुछ हेल्पर-शैली "यूटिलिटी बैग" की समीक्षा कर रहा था, कुछ बड़े सी # कोडबेस के आसपास स्थिर स्थिर कक्षाएं चल रही हैं, जो मूल रूप से निम्नलिखित बहुत ही संक्षिप्त स्निपेट जैसी चीजें हैं:

// Helpers.cs

public static class Helpers
{
    public static void DoSomething() {}
    public static void DoSomethingElse() {}
}

मैंने जिन विशिष्ट तरीकों की समीक्षा की है वे हैं

  • ज्यादातर एक दूसरे से असंबंधित,
  • स्पष्ट राज्य के बिना चालान के पार,
  • छोटा, और
  • प्रत्येक असंबंधित प्रकार के विभिन्न प्रकारों द्वारा सेवन किया जाता है।

संपादित करें: ऊपर कथित समस्याओं की एक सूची होने का इरादा नहीं है। यह उन विशिष्ट विधियों की सामान्य विशेषताओं की सूची है जिनकी मैं समीक्षा कर रहा हूं। यह अधिक प्रासंगिक समाधान प्रदान करने में मदद करने के लिए संदर्भ है।

बस इस प्रश्न के लिए, मैं इस तरह की विधि को GLUM (सामान्य हल्के उपयोगिता विधि) के रूप में संदर्भित करूंगा। "चमक" का नकारात्मक अर्थ आंशिक रूप से अभिप्रेत है। मुझे खेद है कि अगर यह एक मूक दंड के रूप में सामने आता है।

यहां तक ​​कि GLUMs के बारे में अपने स्वयं के डिफ़ॉल्ट संदेह को अलग रखते हुए, मुझे इस बारे में निम्नलिखित बातें पसंद नहीं हैं:

  • एक स्थिर वर्ग को नाम मात्र के रूप में उपयोग किया जा रहा है।
  • स्थिर वर्ग पहचानकर्ता मूल रूप से अर्थहीन है।
  • जब एक नया GLUM जोड़ा जाता है, या तो (ए) यह "बैग" वर्ग बिना किसी अच्छे कारण के छू जाता है या (बी) एक नया "बैग" वर्ग बन जाता है (जो अपने आप में आमतौर पर एक मुद्दा नहीं है; नया क्या बुरा है) स्थिर कक्षाएं अक्सर असंबंधित समस्या को दोहराती हैं, लेकिन कम विधियों के साथ)।
  • मेटा-नामकरण, अपरिहार्य रूप से भयंकर, गैर मानक, और आमतौर पर आंतरिक रूप से असंगत है कि क्या यह है Helpers, Utilities, या जो कुछ भी।

इसे फिर से तैयार करने के लिए एक बहुत अच्छा और सरल पैटर्न क्या है, जो उपरोक्त चिंताओं को संबोधित कर रहा है, और अधिमानतः संभव है कि एक स्पर्श जितना संभव हो?

मुझे शायद जोर देना चाहिए: जिन सभी तरीकों से मैं निपट रहा हूं वे एक-दूसरे से असंबंधित हैं। वहाँ उन्हें अभी भी बहु सदस्यीय स्थिर वर्ग विधि-बैग में बारीक-दाने में तोड़ने का एक उचित तरीका नहीं लगता है।


1
GLUMs ™ के बारे में: मुझे लगता है कि "हल्के" के लिए संक्षिप्त नाम हटाया जा सकता है, क्योंकि सर्वोत्तम प्रथाओं का पालन करके तरीकों को हल्का होना चाहिए;)
फैबियो

@ फैबियो मैं सहमत हूँ। मैंने इस शब्द को एक (संभवतः बहुत अजीब और संभवतः भ्रमित करने वाला) मजाक के रूप में शामिल नहीं किया जो इस प्रश्न के लिखने के लिए एक संक्षिप्त नाम के रूप में कार्य करता है। मुझे लगता है कि "लाइटवेट" यहाँ उचित लग रहा था क्योंकि प्रश्न में कोडबेस लंबे समय तक जीवित रहे, विरासत, और थोड़ा गड़बड़ है, अर्थात कई अन्य तरीके (आमतौर पर ये जीयूएम; न;; जो कि "हैवीवेट") होते हैं। यदि मेरे पास इस समय अधिक (ईम, कोई भी) बजट था, तो मैं निश्चित रूप से अधिक आक्रामक रुख अपनाऊंगा और बाद वाले को संबोधित करूंगा।
विलियम

जवाबों:


17

मुझे लगता है कि आपको दो समस्याएं हैं जो एक-दूसरे से जुड़ी हुई हैं।

  • स्टेटिक कक्षाओं में तार्किक रूप से असंबंधित कार्य होते हैं
  • स्थिर वर्गों के नाम निहित कार्यों के अर्थ / संदर्भ के बारे में उपयोगी जानकारी प्रदान नहीं करते हैं।

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

चिंता और संभव समाधान

तरीके ज्यादातर एक दूसरे से असंबंधित होते हैं - समस्या। संबंधित विधियों को एक स्थिर वर्ग के अंतर्गत संयोजित करें और असंबंधित विधियों को अपने स्वयं के स्थिर वर्गों में स्थानांतरित करें।

विधियां स्पष्ट स्थिति के बिना होती हैं, जो पूरे आक्रमण में बनी रहती हैं - समस्या नहीं। स्टेटलेस तरीके एक विशेषता हैं, बग नहीं। स्टेटिक स्टेट को वैसे भी परखना मुश्किल है, और इसका उपयोग केवल तभी किया जाना चाहिए जब आपको विधि इनवोकेशन के दौरान स्थिति बनाए रखने की आवश्यकता होती है, लेकिन ऐसा करने के बेहतर तरीके हैं जैसे कि स्टेट मशीन और yieldकीवर्ड।

तरीके छोटे हैं - समस्या नहीं है। - तरीके छोटे होने चाहिए

विधियाँ प्रत्येक प्रकार के असंबंधित प्रकारों से होती हैं - समस्या नहीं। आपने एक सामान्य विधि बनाई है जिसका उपयोग कई संबंधित स्थानों में फिर से किया जा सकता है।

एक स्थिर वर्ग को नाम मात्र के रूप में इस्तेमाल किया जा रहा है - समस्या नहीं। इस प्रकार स्थैतिक तरीकों का उपयोग किया जाता है। यदि कॉलिंग विधियों की यह शैली आपको परेशान करती है, तो विस्तार विधियों या using staticघोषणा का उपयोग करने का प्रयास करें ।

स्थिर वर्ग पहचानकर्ता मूल रूप से अर्थहीन - समस्या है । यह अर्थहीन है क्योंकि डेवलपर्स इसमें असंबंधित तरीके डाल रहे हैं। असंबंधित विधियों को अपने स्वयं के स्थिर वर्गों में रखें और उन्हें विशिष्ट और समझने योग्य नाम दें।

जब एक नया GLUM जोड़ा जाता है, या तो (ए) यह "बैग" वर्ग छुआ जाता है (एसआरपी उदासी) - समस्या नहीं है यदि आप इस विचार का पालन करते हैं कि केवल तार्किक रूप से संबंधित विधियां एक स्थिर वर्ग में होनी चाहिए। SRPयहां उल्लंघन नहीं किया जाता है, क्योंकि सिद्धांत को कक्षाओं के लिए या विधियों के लिए लागू किया जाना चाहिए। स्थिर वर्गों की एकल जिम्मेदारी का अर्थ है एक सामान्य "विचार" के लिए अलग-अलग विधियां शामिल करना। वह विचार एक विशेषता या रूपांतरण, या पुनरावृत्तियों (LINQ), या डेटा सामान्यीकरण, या सत्यापन हो सकता है ...

या कम बार (बी) एक नया "बैग" वर्ग बनाया जाता है (अधिक बैग) - समस्या नहीं। क्लास / स्टैटिक क्लासेस / फ़ंक्शंस - हमारे (डेवलपर्स) टूल हैं, जिनका उपयोग हम सॉफ्टवेयर डिज़ाइन करने के लिए करते हैं। क्या आपकी टीम में कक्षाओं के उपयोग की कुछ सीमाएँ हैं? "अधिक बैग" के लिए अधिकतम सीमाएं क्या हैं? प्रोग्रामिंग सभी संदर्भों के बारे में है, यदि आपके विशेष संदर्भ में समाधान के लिए आप 200 स्थैतिक वर्गों के साथ समाप्त होते हैं, जिसे समझदारी से नाम दिया गया है, तार्किक रूप से तार्किक पदानुक्रम के साथ नाम स्थान / फ़ोल्डर में रखा गया है - यह कोई समस्या नहीं है।

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


यह SRP उल्लंघन नहीं है, लेकिन स्पष्ट रूप से एक खुला / बंद सिद्धांत उल्लंघन है। उस ने कहा, मैंने आमतौर पर Ocp को अधिक परेशानी के लायक पाया है
पॉल

2
@Paul, Open / Close सिद्धांत को स्थिर वर्गों के लिए लागू नहीं किया जा सकता है। यह मेरी बात थी, एसआरपी या ओसीपी सिद्धांतों को स्थिर वर्गों के लिए लागू नहीं किया जा सकता है। आप इसे स्टैटिक विधियों के लिए लागू कर सकते हैं।
फैबियो

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

1
"नाम के रूप में स्थिर वर्ग" को फिर से लिखें, यह एक सामान्य पैटर्न है इसका मतलब यह नहीं है कि यह एक विरोधी पैटर्न नहीं है। विधि (जो मूल रूप से एक "नि: शुल्क कार्य" है जो इस विशेष रूप से निम्न-सामंजस्य स्थैतिक वर्ग के भीतर C / C ++ से एक शब्द उधार लेने के लिए है) इस मामले में सार्थक इकाई है। इस विशेष संदर्भ में, एक एकल फ़ाइल में 100 विधियों के साथ Aएक स्थिर वर्ग की तुलना में 100 एकल-विधि स्थिर वर्गों (100 फ़ाइलों में) के साथ उप-नाम स्थान होना संरचनात्मक रूप से बेहतर लगता है A
विलियम

1
मैंने आपके जवाब पर कुछ हद तक सफाई की, ज्यादातर कॉस्मेटिक। मुझे यकीन नहीं है कि आपका अंतिम पैराग्राफ किस बारे में है; किसी को इस बात की चिंता नहीं है कि वे कोड का परीक्षण कैसे कर रहे हैं जो Mathस्थिर वर्ग को बुलाता है ।
रॉबर्ट हार्वे

5

बस इस कन्वेंशन को गले लगाओ कि स्थिर वर्ग का उपयोग सी # में इस तरह की स्थितियों में नामस्थान की तरह किया जाता है। नामस्थानों को अच्छे नाम मिलते हैं, इसलिए इन वर्गों को चाहिए। using staticC # 6 की सुविधा जीवन को थोड़ा आसान भी बनाती है।

बदबूदार वर्ग नाम Helpersसंकेत की तरह है कि तरीकों को बेहतर-नामित स्थिर वर्गों में विभाजित किया जाना चाहिए, यदि संभव हो तो, लेकिन आपकी एक जोर वाली धारणा यह है कि आपके द्वारा व्यवहार किए जाने वाले तरीके "जोड़ीदार असंबंधित" हैं, जिसका अर्थ है विभाजित करना मौजूदा पद्धति के अनुसार एक नया स्थिर वर्ग। शायद ठीक है, अगर

  • देखते हैं अच्छा नाम नई स्थिर कक्षाओं के लिए और
  • आप इसे वास्तव में अपनी परियोजना की स्थिरता को लाभ देने के लिए न्याय करते हैं।

एक उदाहरण के रूप में, Helpers.LoadImageकुछ ऐसा बन सकता है FileSystemInteractions.LoadImage

फिर भी, आप स्थैतिक वर्ग विधि-बैग के साथ समाप्त हो सकते हैं। यह हो सकता है कुछ तरीके:

  • हो सकता है कि मूल तरीकों में से केवल कुछ (या कोई नहीं) उनके नए वर्गों के लिए अच्छे नाम हैं।
  • हो सकता है कि नई कक्षाएं बाद में अन्य प्रासंगिक विधियों को शामिल करने के लिए विकसित हों।
  • शायद मूल वर्ग का नाम बदबूदार नहीं था और वास्तव में ठीक था।

यह याद रखना महत्वपूर्ण है कि ये स्थिर वर्ग विधि-बैग वास्तविक C # कोडबेस में बहुत असामान्य नहीं हैं। यह शायद कुछ छोटे लोगों के लिए पैथोलॉजिकल नहीं है


यदि आप वास्तव में अपनी फ़ाइल में प्रत्येक "फ्री फंक्शन" जैसी विधि होने में एक फायदा देखते हैं (जो ठीक है और सार्थक है यदि आप ईमानदारी से न्याय करते हैं कि यह वास्तव में आपकी परियोजना की स्थिरता को लाभ देता है), तो आप एक स्थिर के बजाय इस तरह के एक स्थिर वर्ग बनाने पर विचार कर सकते हैं। आंशिक वर्ग, स्थैतिक वर्ग के नाम को नियोजित करने के समान है कि आप एक नाम स्थान और फिर इसके माध्यम से कैसे उपभोग करेंगे using static। उदाहरण के लिए:

इस पैटर्न का उपयोग करके डमी परियोजना की संरचना

Program.cs

namespace ConsoleApp1
{
    using static Foo;
    using static Flob;

    class Program
    {
        static void Main(string[] args)
        {
            Bar();
            Baz();
            Wibble();
            Wobble();
        }
    }
}

फू / Bar.cs

namespace ConsoleApp1
{
    static partial class Foo
    {
        public static void Bar() { }
    }
}

फू / Baz.cs

namespace ConsoleApp1
{
    static partial class Foo
    {
        public static void Baz() { }
    }
}

Flob / Wibble.cs

namespace ConsoleApp1
{
    static partial class Flob
    {
        public static void Wibble() { }
    }
}

Flob / Wobble.cs

namespace ConsoleApp1
{
    static partial class Flob
    {
        public static void Wobble() { }
    }
}

-6

आम तौर पर आपको किसी भी "सामान्य उपयोगिता विधियों" की आवश्यकता नहीं होनी चाहिए। आपके व्यावसायिक तर्क में। एक और कठोर रूप लें और उन्हें एक उपयुक्त स्थान पर रखें।

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

मानक डेटाटाइप पर फ़ंक्शंस जोड़ने के लिए आप एक्सटेंशन मेथड्स का उपयोग कर सकते हैं।

उदाहरण के लिए, मान लीजिए कि मेरे पास हेल्पर्स के बजाय एक सामान्य फ़ंक्शन MySort () है। मेरा नाम या एक नई ListOfMyThings जोड़ रहा है। मेरे द्वारा इसे IEnumerable में जोड़ सकते हैं


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

1
यदि आप नहीं करते है "सामान्य उपयोगिता के तरीकों," आप शायद तर्क के टुकड़े अपने तर्क काफी के बाकी हिस्सों से अलग नहीं कर रहे हैं। उदाहरण के लिए, जहाँ तक मुझे पता है, .NET में फ़ंक्शन से जुड़ने का कोई सामान्य उद्देश्य URL पथ नहीं है, इसलिए मैं अक्सर एक लिखना समाप्त करता हूं। मानक पुस्तकालय के हिस्से के रूप में उस तरह का क्रॉफ्ट बेहतर होगा, लेकिन हर मानक के लिए कुछ छूट रहा है । विकल्प, तर्क को आपके अन्य कोड के अंदर सीधे दोहराया जाना, इसे बहुत कम पठनीय बनाता है ।
jpmc26


1
@ ईवन जो एक फ़ंक्शन नहीं है, यह एक सामान्य प्रयोजन प्रतिनिधि हस्ताक्षर है ...
21

1
@ इवान यह था TheCWWhisperer का पूरा बिंदु: उपयोगिता वर्ग एक कक्षा में विधियाँ डालने के लिए एक कीचड़ है। खुशी है कि आप सहमत हैं।
jpmc26
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.