2009-11-04 15 views
11

मैं पढ़ रहा हूं कि कोड में स्थैतिक वर्ग/सिंगलेट्स का उपयोग करके निर्भरताएं बनाना, खराब रूप है, और समस्याएं उत्पन्न करता है। तंग युग्मन, और इकाई परीक्षण।उपयोगिता कक्षाएं .. अच्छा या बुरा?

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

अतीत में मैं एक वर्ग बना सकते हैं और इन तरीकों जोड़ सकते हैं और उन्हें अपने कोड जैसे से सीधे फोन पर आगे बढ़ गए हैं।

UrlParser.ParseUrl(url); 

लेकिन एक मिनट प्रतीक्षा करें, जो किसी अन्य वर्ग पर निर्भरता पेश कर रहा है। मुझे यकीन है कि ये 'उपयोगिता' वर्ग खराब हैं, क्योंकि वे स्टेटलेस हैं और यह स्थिर स्थिर वर्गों और सिंगलेट्स के साथ कुछ समस्याओं को कम करता है। क्या कोई इसे स्पष्ट कर सकता है?

मैं बुला वर्ग के लिए तरीकों से आगे बढ़ जाना चाहिए, वह यह है कि अगर केवल बुला वर्ग विधि का उपयोग किया जाएगा। यह 'एकल जिम्मेदार सिद्धांत' का उल्लंघन कर सकता है।

+0

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

+0

शुद्ध कार्यों बुलाया जाएगा (जावा के बारे में ज्यादातर बात कर, लेकिन अभी भी यहाँ प्रासंगिक): http://www.yegor256.com/2014/05/05/oop-alternative-to-utility-classes। एचटीएमएल – yegor256

उत्तर

7

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

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

उदाहरण के लिए, आपके मामले में, मुझे लगता है कि UrlParser.ParseUrl (...) शायद बेहतर एक वर्ग के रूप नियंत्रित किया जाता है लग रहा है। बीसीएल में System.Uri देखें - यह एक समान, उपयोग करने योग्य इंटरफ़ेस के लिए एक आसान, उपयोग करने योग्य इंटरफ़ेस को संभालता है, जो अच्छी तरह से काम करता है, और वास्तविक स्थिति को बनाए रखता है। मैं इस दृष्टिकोण को एक उपयोगिता विधि के लिए पसंद करता हूं जो तारों पर काम करता है, और उपयोगकर्ता को एक स्ट्रिंग के चारों ओर गुजरने के लिए मजबूर करता है, इसे सत्यापित करने के लिए याद रखें, आदि

+0

अच्छा बिंदु। System.Uri इस तरह की एक स्थिर उपयोगिता विधि को किसी ऑब्जेक्ट में परिवर्तित करने का एक अच्छा उदाहरण है। –

+0

यह भी उनकी विशिष्ट प्रश्न के लिए बहुत प्रासंगिक है, उनके उदाहरण दिया;) –

+0

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

0

वे ठीक हो जब तक आप उन्हें अच्छी तरह से डिजाइन के रूप में (यह है कि आप समय-समय पर उनके हस्ताक्षर को बदलने के लिए नहीं है)।

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

चूंकि ये उपयोगिता विधियां कभी नहीं बदलेगी, अक्सर मैं कहूंगा कि यह बहुत अधिक समस्या नहीं है।

मुझे लगता है कि यह सबसे खराब होगा यदि आप कॉपी/बार-बार एक ही उपयोगिता विधि पेस्ट होगा।

यह वीडियो How to design a good API and why it matters जोशुआ ब्लोच द्वारा, एपीआई को डिजाइन करते समय ध्यान में रखने के लिए कई अवधारणाओं को बताता है (जो आपकी उपयोगिता लाइब्रेरी होगी)। हालांकि वह एक मान्यता प्राप्त जावा वास्तुकार है, लेकिन सामग्री सभी प्रोग्रामिंग भाषाओं पर लागू होती है।

2

उपयोगिता कक्षाएं ठीक हैं ..... जब तक वे डिजाइन सिद्धांतों का उल्लंघन नहीं करते हैं। कोर फ्रेमवर्क कक्षाओं का उपयोग करने के रूप में उन्हें खुशी से उपयोग करें।

कक्षाओं का नाम अच्छी तरह से नामित और तार्किक होना चाहिए। असल में वे इतनी ज्यादा "उपयोगिता" नहीं हैं, लेकिन एक उभरते हुए फ्रेमवर्क का हिस्सा है जो देशी वर्ग प्रदान नहीं करते हैं।

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

2

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

प्रश्न बन जाता है, क्या यह वास्तव में प्रयास के लायक है? कुछ प्रणालियों में, हाँ में जवाब, लेकिन दूसरों में, विशेष रूप से छोटे, जवाब शायद नहीं है।

+0

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

+0

इंजेक्शन निर्भरता को दूर नहीं करता है। यह सिर्फ इसे संभालना आसान बनाता है। – OscarRyz

+0

** ** निर्भरता को हटाने का एकमात्र तरीका इसे निकालना है। मुझे तुम्हारा बिंदु नहीं दिख रहा है। –

1

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

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

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

1

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

0

उनका सीमित प्रयोग करें, तो आप अपने वर्गों में आप कर सकते हैं जितना तर्क डाल करने के लिए तो वे सिर्फ डेटा कंटेनर बन न चाहते हैं।

लेकिन, एक ही समय तुम सच में utilites टाल नहीं सकते पर, वे कभी कभी आवश्यक हैं।

इस मामले में मुझे लगता है कि यह ठीक है।

FYI करें वहाँ system.web.httputility वर्ग जो आम http उपयोगिताओं जो आपके लिए उपयोगी हो सकता है की बहुत कुछ होता है।

1

यह वास्तव में संदर्भ पर निर्भर करता है, और हम इसका उपयोग कैसे करते हैं।

उपयोगिता वर्ग, स्वयं, बुरा नहीं है। हालांकि, अगर हम इसे खराब तरीके से इस्तेमाल करते हैं तो यह खराब हो जाएगा। प्रत्येक डिजाइन पैटर्न (विशेष रूप से सिंगलटन पैटर्न) को आसानी से एंटी-पैटर्न में बदल दिया जा सकता है, वही उपयोगिता वर्गों के लिए जाता है।

सॉफ्टवेयर डिजाइन में, हम लचीलापन & सादगी के बीच एक संतुलन की जरूरत है।यदि हम एक स्ट्रिंगयूल्ट बनाने जा रहे हैं जो केवल स्ट्रिंग-मैनिपुलेशन के लिए ज़िम्मेदार है:

  • क्या यह एसआरपी (एकल जिम्मेदारी सिद्धांत) का उल्लंघन करता है? -> नहीं, यह डेवलपर्स हैं जो एसआरपी का उल्लंघन करने वाले उपयोगिता वर्गों में बहुत अधिक जिम्मेदारियां डालते हैं।
  • "यह डि चौखटे का उपयोग कर इंजेक्शन नहीं किया जा सकता" -> रहे हैं StringUtils कार्यान्वयन करने वाले अलग-अलग होता? क्या हम रनटाइम पर अपने कार्यान्वयन स्विच कर रहे हैं? क्या हम इसका मज़ाक उड़ा रहे हैं? बिलकूल नही।

=> उपयोगिता कक्षाएं, themselve, बुरा नहीं हैं। यह डेवलपर्स की गलती है जो इसे खराब बनाती है।

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

संबंधित मुद्दे