C # में "स्टेटिक" का उपयोग न करें?


109

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

मैंने जाँच की और पूरी तरह से मेरी 1/4 कक्षाएं "स्टैटिक" चिह्नित हैं। जब मैं किसी वर्ग का उदाहरण बनाने के लिए नहीं जा रहा हूं, तो मैं स्थैतिक का उपयोग करता हूं क्योंकि वर्ग एक ही वैश्विक वर्ग है जिसका उपयोग पूरे कोड में किया जाता है।

उन्होंने कहा कि मॉकिंग, आईओसी / डीआई तकनीकों को शामिल करने के लिए कुछ चीजों का उल्लेख किया गया है जिनका उपयोग स्थिर कोड के साथ नहीं किया जा सकता है। उनका कहना है कि जब तीसरी पार्टी लाइब्रेरी अपनी गैर-परीक्षणनीयता के कारण स्थिर है तो यह दुर्भाग्यपूर्ण है।

क्या यह अन्य वास्तुकार सही है?

अद्यतन: यहाँ एक उदाहरण है:

APIManager - यह वर्ग 3 पार्टी एपीआई के शब्दकोश रखता है जिसे मैं अगले अनुमत समय के साथ बुला रहा हूं। यह एपीआई उपयोग की सीमा को लागू करता है कि बहुत से 3 पक्ष उनकी सेवा की शर्तों में हैं। मैं इसे कहीं भी उपयोग करता हूं मैं थर्ड पार्टी सेवा को थ्रेड कहकर कॉल कर रहा हूं। सोलेप (APIManager.GetWait ("ProviderXYZ")); कॉल करने से पहले। यहाँ सब कुछ थ्रेड सुरक्षित है और यह C # में TPL के साथ बहुत अच्छा काम करता है।


37
staticठीक है; static खेतों इलाज किया जाना चाहिए बहुत ध्यान से
मार्क Gravell

2
वह 3 पार्टी पुस्तकालयों के लिए परीक्षण क्यों लिखेंगे? क्या आप सामान्य रूप से सिर्फ अपने ही कोड का परीक्षण नहीं करते हैं, यह मानते हुए कि 3 पार्टी लाइब्रेरी के रचनाकारों ने अपना परीक्षण किया है?
नहीं

3
वह विशेष आपत्ति मेरे लिए थोड़ी सामान्य है। ज्यादातर मामलों में आप स्थैतिक वर्ग का मजाक नहीं उड़ाएंगे, आप तर्कों का मजाक उड़ाएंगे। स्थैतिक क्षेत्र जहां यह एक समग्र वर्ग था जिसे मॉकिंग की आवश्यकता थी, फिर हाँ।

8
स्पष्ट रूप से आपके सहयोगियों की एक गंभीर स्थिति है - एक तीव्र प्रणालीगत ओओपस एरिथेमेटोसस। उन्हें एक उपचार ASAP की आवश्यकता है!
SK-तर्क

6
उत्तर प्रदान करने के लिए एक उत्तर अनुभाग है, मुझे समझ में नहीं आता है कि लोग किसी को उत्तर / सुझाव देने के प्रयास में टिप्पणी क्यों करते हैं ... यह StackExchange के उद्देश्य को पराजित करता है, निश्चित रूप से एक टिप्पणी अधिक जानकारी का अनुरोध करने के लिए होगी।
पेटस्की

जवाबों:


121

यह इस बात पर निर्भर करता है कि स्टेटिक क्लास स्टेट को बनाए रखते हैं या नहीं। निजी तौर पर, मुझे स्टेटिक क्लास में एक साथ फेंके गए स्टेटलेस फंक्शन्स से कोई समस्या नहीं है।


111
सही बात। स्थैतिक कार्य जिनके कोई दुष्प्रभाव नहीं हैं वे सभी के सबसे अधिक परीक्षण योग्य कार्य हैं।
रॉबर्ट हार्वे

9
+1 करने के लिए, लेकिन एक सुरक्षा खंड के साथ: लगभग हर अमूर्त एल्गोरिथ्म स्टेटलेस है, लेकिन इसका मतलब यह नहीं है कि आपको इसे स्टेटलेस स्टेटिक क्लास या विधि के रूप में लागू करना चाहिए। इस तरह से इसे लागू करने से इसका उपयोग करने वाले सभी कोड को शायद ही इससे जोड़ा जा सके। उदाहरण के लिए इसका अर्थ है कि यदि आप एल्गोरिथ्म को एक स्थिर विधि के रूप में लागू करते हैं और इसे प्रोजेक्ट के माध्यम से उपयोग करते हैं - तो आप अस्थायी रूप से छँटाई को दूसरे एल्गोरिथ्म में नहीं बदल सकते हैं, अर्थात् परीक्षण के उद्देश्य से और समस्या क्षेत्र को कम करने के लिए। यह कई मामलों में एक बड़ी बाधा है। उस के अलावा, स्थैतिक पूरी तरह से ठीक है अगर यथोचित उपयोग किया जाता है।

11
संक्षेप में: वे सबसे अधिक परीक्षण योग्य कार्य हैं, लेकिन नहीं कि वे किसी अन्य कोड को अधिक परीक्षण योग्य बनाते हैं ! यह वही है जो आर्किटेक्ट का मतलब था।

4
@ tereško: C # भाषा को स्टैटिक क्लास का हिस्सा होने के लिए स्टैटिक तरीकों की आवश्यकता होती है, यदि आप विधि को कॉल करने के लिए क्लास का एक उदाहरण नहीं बनाना चाहते हैं। शायद आपका मतलब है "उदाहरण," और "क्लास" नहीं।
रॉबर्ट हार्वे

8
@quetzalcoatl: एक प्रतिनिधि (यानी एक अलग एल्गोरिथ्म) को एक स्थिर विधि से पारित करना पूरी तरह से कानूनी है; Linq में विस्तार के तरीके सभी स्थिर तरीके हैं। उदाहरण: msdn.microsoft.com/en-us/library/…
रॉबर्ट हार्वे

93

वह इसके बारे में बहुत सामान्य है। वह सही है, यह परीक्षण में बाधा डालता है। हालांकि, staticकक्षाओं और विधियों का अपना स्थान है और यह वास्तव में संदर्भ पर निर्भर करता है। कोड उदाहरणों के बिना आप वास्तव में नहीं बता सकते।

जब मैं किसी वर्ग का उदाहरण बनाने के लिए नहीं जा रहा हूं, तो मैं स्थैतिक का उपयोग करता हूं क्योंकि वर्ग एक ही वैश्विक वर्ग है जिसका उपयोग पूरे कोड में किया जाता है।

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

यदि आप उन्हें विस्तार विधियों या सहायकों के लिए उपयोग कर रहे हैं जो राज्य को नहीं बदलते हैं और बस आपके द्वारा प्रदान किए गए मापदंडों पर काम करते हैं, तो वे आमतौर पर ठीक होते हैं।


3
+1 यह उल्लेख करने के लिए कि कथन सामान्य था और विस्तार विधियों का उल्लेख था, जिसका परीक्षण भी किया जा सकता है और जहां तक ​​मुझे पता है निर्भरता का अभी भी मजाक उड़ाया जा सकता है।
नहीं

4
ऐ स्टैटिक सिंगलटन के रूप में सिंगल क्लास इंस्टेंस के रूप में ऐय स्टैटिक, जो गन्दा होने जा रहा है ....

"एक डेटाबेस का उपयोग करने के लिए?" क्यों नहीं ? यदि टेबल एडेप्टर स्थिर नहीं है, तो एक स्थिर वर्ग @ दृढ़ता से टाइप किए गए डेटासेट बनाने, इसके साथ कुछ भी गलत नहीं है .... जब तक आप संदर्भ या उदाहरण के साथ अपनी बात साबित नहीं करते हैं?
गणित

27

मैंने जाँच की और पूरी तरह से मेरी 1/4 कक्षाएं "स्टैटिक" चिह्नित हैं। जब मैं किसी वर्ग का उदाहरण बनाने के लिए नहीं जा रहा हूं, तो मैं स्थैतिक का उपयोग करता हूं क्योंकि वर्ग एक ही वैश्विक वर्ग है जिसका उपयोग पूरे कोड में किया जाता है।

सबसे अच्छी बात यह है कि अपने कोड को आज़माएं और उसका परीक्षण करें। ऐसे परीक्षण डिज़ाइन करने का प्रयास करें, जो एक समय में केवल एक ही विधि को दोहराने योग्य, स्वतंत्र, सरल और परीक्षण योग्य हों। विभिन्न यादृच्छिक क्रम में अपने परीक्षण चलाने का प्रयास करें। क्या आप स्थिर "हरा" निर्माण प्राप्त कर सकते हैं?

यदि हाँ, तो यह आपके कोड का बचाव करने के लिए एक वैध बिंदु है। यदि, हालांकि, आपको कठिनाइयाँ हैं, तो शायद आपको उदाहरण-आधारित विधियों के लिए जाना चाहिए।


7
यही वह बिंदु है जिसने मुझे भी प्रभावित किया है। कुछ स्थिर और स्टेटलेस 'हेल्पर' शैली की कक्षाएं ठीक हैं, लेकिन अगर आपको अपनी सभी कक्षाओं का पूरा 25% स्थिर के रूप में मिला है, तो यह संभव नहीं है कि आपके प्रयास उस मामले तक सीमित हों।
मैथ्यू शारले

2
@ मैथ्यू शेखरले - उन्हें शायद 4 कक्षाएं मिलीं, और उनमें से 1 स्टेटिक है :)
एलेक्सस

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

11

पहले से ही पोस्ट किए गए उत्तर वास्तव में बहुत अच्छे बिंदुओं को कवर करते हैं, लेकिन एक ऐसा है जो गायब लगता है:

स्थैतिक क्षेत्र कभी भी कचरा एकत्र नहीं होते हैं ।

यह वास्तव में महत्वपूर्ण है यदि आपके पास बहुत अधिक मेमोरी बाधाओं के साथ एक ऐप है, और यह पैटर्न बहुत आम हो सकता है जब लोग कैश को लागू करने का प्रयास करते हैं।

स्थैतिक कार्य लगभग उतने बुरे नहीं हैं, लेकिन बाकी सभी ने इसे पहले से ही पर्याप्त रूप से कवर किया है।


10

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

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

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


टिप्पणीकार मुझे विस्तार के तरीकों की याद दिलाता है, जो निश्चित रूप से सी # में स्थिर कक्षाओं में होना है। यह कानूनी है, और इसका उदाहरण है कि कैसे शुद्ध IoC C # में सुपर अच्छी तरह से काम नहीं करता है, कम से कम यदि आप भाषा की चौड़ाई का लाभ उठाने की कोशिश कर रहे हैं।


1
यदि किसी वर्ग को सही कारणों के लिए स्थैतिक बनाया जाता है और सही तरीके से लागू किया जाता है जैसे उदाहरण विस्तार विधियों के लिए तो वे अभी भी बहुत ही परीक्षण योग्य हैं क्योंकि उनके पास कोई बाहरी निर्भरता नहीं होगी और वे स्व-निहित हैं और जैसे कि उन्हें नकल करने की आवश्यकता नहीं होनी चाहिए। एक शुद्ध IoC / DI परियोजना रखने की खातिर एक व्यवसाय की आवश्यकता को पूरी तरह से भरने के लिए डिज़ाइन की आवश्यकता से प्रेरित इंटरफ़ेस की आवश्यकता नहीं होनी चाहिए?
नहीं

1
आप और मैं इस बात पर सहमत हैं कि आपको सही काम के लिए सही उपकरण का चयन करना चाहिए और दर्शन द्वारा हथकड़ी नहीं लगानी चाहिए। यदि, हालांकि, शुद्ध IoC / DI की आपकी परियोजना में एक अच्छी तरह से स्थापित संस्कृति है, तो यह उतना ही दुख होगा जितना कि एक पारंपरिक रूप से टॉप-डाउन समाधान को IoC / DI में परिवर्तित करने में। इंजीनियरिंग को संक्रमणकालीन लागतों पर विचार करने की आवश्यकता है। वैसे, मुझे नहीं लगता कि विस्तार विधियां आपको वहां मिलती हैं। मुझे लगता है कि स्थिर वर्गों के साथ IoCish व्यवहार के लिए एक बेहतर समाधान पूर्वप्रक्रमक निर्देशों के साथ संकलन समय पर बीच चुना कई वर्गों के लिए किया जाएगा, सी शैली
jwrush

1
एर। मैं गूंगा हूँ। आप विस्तार विधियों के लिए एक स्थिर वर्ग से तात्पर्य रखते हैं, जो निश्चित रूप से, आपको उन्हें कैसे करना है। हां, निश्चित रूप से, आप उस उद्देश्य के लिए एक स्थिर वर्ग चाहते हैं। इससे मेरा दिमाग खिसक गया: और यह दिखाने के लिए कि C # IoC के लिए नहीं था। :)
वृहस्पति

हां, आप सही हैं, अगर किसी मौजूदा परियोजना में एक मौजूदा संस्कृति मौजूद है तो चीजों को करने के तरीके को बदलने में मदद करने से ज्यादा नुकसानदायक होगा।
नहीं

5

स्थैतिक वर्गों का कभी-कभी दुरुपयोग किया जाता है और होना चाहिए:

  • एक सिंगलटन (जहां गैर-स्थिर वर्ग के पास एक स्थिर सदस्य और एक सार्वजनिक स्थैतिक इंस्टेंस चर है, इसे केवल एक बार प्राप्त करने / बनाने के लिए है।
  • एक अन्य वर्ग में एक विधि (जहां राज्य मायने रखता है)। यदि आपके पास कोई सदस्य है जो उस वर्ग के डेटा का उपयोग नहीं कर रहा है, तो शायद उसे उस वर्ग का हिस्सा नहीं होना चाहिए।

यह एक तथाकथित 'उपयोगिता' फ़ंक्शन और उपयोगिता वर्ग का हिस्सा भी हो सकता है। उपयोगिता वर्ग ऐसी कक्षाएं हैं जिनमें केवल स्थिर विधियां होती हैं और बिना किसी संदर्भ के सहायक कार्यों के रूप में कार्य करती हैं।


@topomorto क्योंकि क्लास को उसके निर्माता द्वारा त्वरित नहीं किया जाना चाहिए जिसके परिणामस्वरूप कई ऑब्जेक्ट्स / इंस्टेंसेस होते हैं, लेकिन एक विशेष विधि (सामान्य रूप से उदाहरण ()) से <जो हमेशा एक ही उदाहरण देता है, पहली कॉल इंस्टेंस () के तुरंत बाद।
मिशेल किजर्स

@topomorto मैंने अभी जाँच की है और आप पूरी तरह से सही हैं, केवल कुछ सदस्य स्थिर हैं (उदाहरण चर और उदाहरण फ़ंक्शन)। मैं उसी के अनुसार अपना उत्तर बदलूंगा; उल्लेख करने के लिए धन्यवाद।
मिशेल किजर्स 21

4

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


1

मैं उन चीजों के लिए स्थैतिक गुणों का उपयोग कर रहा हूं जो एक वर्ग के सभी उदाहरणों के लिए सामान्य हैं। और मैं क्लास ऑब्जेक्ट्स के समूह प्राप्त करने के लिए स्थैतिक तरीकों का उपयोग कर रहा हूं। मैं किसी भी तरह से एक विशेषज्ञ नहीं हूं, लेकिन यह मेरे लिए अब तक काम कर रहा है।

PHP उदाहरण:

class vendorData {
  private static $data_table = 'vendor_data'; // static property
  private $id; // instance property
  private $name; // instance property

  public function __construct($vendor_id) {
    if(!self::validId($vendor_id) ) { // static method
      return false; // id doesn't exist
    }
    $this->id = $vendor_id; // id has been validated
    $this->getProperties(); // object method
  }

  private static function validId($vendor_id) {
    // send db query to find if the id exists
    // return true/false;
  }

  private function getProperties() { // object method
    $sql = "SELECT * FROM `{self::$data_table}` // using static property
        WHERE `id` = {$this->id}"; // using object instance property
    // get resultset
    foreach($result as $property => $value) {
      $this->$property = $value; // object instance properties all set
    }
  }

  // and here
  public static function getBy($property,$value) { // static method to return object array
    $sql = "SELECT `id` FROM `{self::$data_table}` // using static property
      WHERE `$property` = '$value'";
    // send query, get $ids array
    $obj_array = array();
    foreach($ids as $id) {
      // create array of current class objects using special static keyword
      // meaning of static here is different than in property/method declarations
      $obj_array[$id] = new static($id);
    }
    return $obj_array;
  }
}

1

मैं कहता हूँ कि वे सिद्धांत ठीक हैं, लेकिन कथन (स्टेटिक्स का उपयोग न करें) गलत हो सकता है। आपका कोड कवरेज कितना है? यदि संख्या अधिक है और आप अपने ऐप के यूनिट परीक्षण के साथ सहज हैं, तो आप ठीक हैं। यदि नहीं, तो मैं कोड की समीक्षा करने का सुझाव दूंगा। आप पा सकते हैं कि स्थिर कक्षाएं इसका कारण हैं या नहीं, यह बहुत सी चीजों पर निर्भर करेगा।


-3

स्थिर विधियों वाली कक्षाएं OOP के सिद्धांतों का दुरुपयोग करती हैं। यह पहले से ही OOP नहीं है, यह COP- क्लास-ओरिएंटेड प्रोग्रामिंग है।

उनके पास शायद ही कभी स्पष्ट "व्यक्तित्व" हो (मैं अपने पसंदीदा मानव रूपक का उपयोग यहां करता हूं ), या पहचान। इसलिए वे नहीं जानते कि वे कौन हैं। यह बिंदु अकेले OOP में इस अवधारणा से छुटकारा पाने के लिए पर्याप्त है, लेकिन उनमें से अधिक हैं।

अगले एक पहले बिंदु का परिणाम है। चूंकि ऐसी कक्षाएं नहीं जानती हैं कि वे कौन हैं, वे बड़े से बड़े होते हैं।

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

धीरे-धीरे, लेकिन अनिवार्य रूप से, आपके कोड की कम और कम सामंजस्यपूर्ण हो रही है, क्योंकि छिपी निर्भरताएं खराब तरीके से नियंत्रित होती हैं। वे अदृश्य लगते हैं। और एक दूसरे को जोड़ना इतना आसान है! आपको किसी भी विधि के हस्ताक्षर को संशोधित करने की आवश्यकता नहीं है। आपको बस एक स्थिर विधि को कॉल करना है। और क्या एक बदसूरत कोड निम्नानुसार है ...

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

स्थैतिक तरीकों के बजाय क्या उपयोग करें? खैर, मेरा सुझाव OOP है। इसे क्यों न आजमाया जाए?

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.