क्या रिफैक्टरिंग प्रयोजनों के लिए सिर्फ गुणों के साथ एक वर्ग होना ठीक है?


79

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


नीचे दिए गए उत्तर अच्छे हैं। मैंने हमेशा इस उद्देश्य के लिए एक कक्षा की स्थापना की। क्या आप स्वचालित गुणों का उपयोग कर रहे हैं? msdn.microsoft.com/en-us/library/bb384054.aspx
हार्व

अन्यथा POD (सादे-पुराने-डेटा) प्रकार के रूप में जाना जाता है।
new123456

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

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

@ मिचेल: मैं आपसे सहमत हूं। एक और बिंदु - मेरा मानना ​​है कि आपको विधि को समर्पित वस्तु नहीं बनाना चाहिए जब तक कि उसके आंतरिक का विधि के बाहर संबंध नहीं हो।
शनि टेक्नॉलॉजीज

जवाबों:


75

यह एक लाजवाब विचार है। यह आमतौर पर उदाहरण के लिए WCF में डेटा अनुबंध कैसे किया जाता है।

इस मॉडल का एक फायदा यह है कि यदि आप एक नया पैरामीटर जोड़ते हैं, तो क्लास के उपभोक्ता को केवल पैरामीटर जोड़ने के लिए बदलने की आवश्यकता नहीं है।

जैसा कि डेविड हेफर्नन का उल्लेख है, यह कोड को स्व दस्तावेज़ में मदद कर सकता है:

FrobRequest frobRequest = new FrobRequest
{
    FrobTarget = "Joe",
    Url = new Uri("http://example.com"),
    Count = 42,
};
FrobResult frobResult = Frob(frobRequest);

महान। मैं इस धारणा के तहत था कि सिर्फ गुणों वाला कोई वर्ग नहीं था और कोई भी तरीका बेकार नहीं था।
Xaisoft

2
यदि इसमें केवल डेटा सदस्य होंगे, तो मैं इसे संरचित करना पसंद करता हूं। संरचना का उपयोग यह धारणा देता है कि यह केवल डेटा है।
यूसुफ

28
संरचना का उपयोग करने के पास पास शब्दार्थों पर प्रतिलिपि जैसे दुष्प्रभाव हैं। कृपया सुनिश्चित करें कि इस तरह का निर्णय लेने से पहले आप इसके बारे में जानते हैं
एड्रियन ज़ैनस्कु

यह कैसे जावास्क्रिप्ट मॉड्यूल आमतौर पर लिखा जाता है, और यह मॉड्यूल परिपक्वता के रूप में अधिक या कम पैरेम्स को स्वीकार करने के लिए सबसे अच्छा तरीका लगता है। someFunction ({myParam1: 'something', myParam2: 'somethingElse'});
क्रिस्टियन

63

हालांकि यहां अन्य उत्तर सही ढंग से इंगित करते हैं कि किसी कक्षा का एक उदाहरण पास करना 30 मापदंडों को पारित करने से बेहतर है, ध्यान रखें कि बड़ी संख्या में पैरामीटर अंतर्निहित मुद्दे का लक्षण हो सकते हैं।

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

वैकल्पिक रूप से, मापदंडों को एक उच्च अमूर्त स्तर की वस्तुओं में समूह बनाने के तरीकों की तलाश करें। एक एकल वर्ग में असंबंधित मापदंडों का एक गुच्छा डंप करना एक अंतिम उपाय आईएमओ है।

देखें कि कितने पैरामीटर कितने हैं? इस पर कुछ और विचारों के लिए।


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

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

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

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

3
एक और संभावित परिदृश्य यह है कि सभी पैरामीटर संबंधित हैं, लेकिन वे खराब रूप से व्यवस्थित हैं। यह काफी संभावना है कि मापदंडों के समूहों को टुकड़े टुकड़े के आसपास पारित होने के बजाय अलग-अलग वस्तुओं में बांधा जाना चाहिए। कहो कि मेरे पास एक ऐसी विधि है जो "व्यक्ति", "पता", "पर्चे" जैसी जानकारी पर काम करती है ... जो कि आसानी से 30 मापदंडों तक पहुंच सकती है यदि जानकारी के प्रत्येक असतत टुकड़े को अलग से मेरी विधि में पारित किया गया था।
नैट सीके

25

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

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


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

15

जब तक किसी Parameter Object को Refactoring करना अपने आप में एक बुरा विचार नहीं है, इसका इस्तेमाल इस समस्या को छिपाने के लिए नहीं किया जाना चाहिए कि एक वर्ग जिसे कहीं और से प्रदान किए गए 30 टुकड़े डेटा की आवश्यकता है, फिर भी एक कोड गंध का कुछ हो सकता है। परिचय पैरामीटर ऑब्जेक्ट रिफैक्टरिंग को संभवतः उस प्रक्रिया के अंत के बजाय एक व्यापक रिफैक्टिंग प्रक्रिया में एक कदम के रूप में माना जाना चाहिए।

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

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


10

यह एक उत्कृष्ट विचार है और समस्या का एक बहुत ही सामान्य समाधान है। 2 या 3 से अधिक मापदंडों वाले तरीकों को तेजी से समझने के लिए कठिन और कठिन हो जाता है।

यह सब एक ही वर्ग में एनकैप्सुलेट करना बहुत स्पष्ट कोड बनाता है। क्योंकि आपके गुणों के नाम हैं आप इस तरह से स्व-दस्तावेजीकरण कोड लिख सकते हैं:

params.height = 42;
params.width = 666;
obj.doSomething(params);

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

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


9

मार्टिन फाउलर ने अपनी पुस्तक Refactoring में इस परिचय पैरामीटर वस्तु को कॉल किया । उस उद्धरण के साथ, कुछ इसे एक बुरा विचार कहेंगे।


1
हाँ, लेकिन 30 मापदंडों के लिए, कहीं न कहीं कुछ गलत है, जिसे पहले तय करना है
मनोज्ञ

5

30 पैरामीटर एक गड़बड़ है। मुझे लगता है कि यह एक तरह से गुणों के साथ एक वर्ग है। आप एक ही श्रेणी में फिट होने वाले मापदंडों के समूहों के लिए कई "पैरामीटर कक्षाएं" भी बना सकते हैं।


3

आप एक वर्ग के बजाय एक संरचना का उपयोग करने पर भी विचार कर सकते हैं।

लेकिन आप जो करने की कोशिश कर रहे हैं वह बहुत सामान्य और एक महान विचार है!


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

क्यों डेविड? खेतों की संख्या का इससे क्या लेना-देना है? बस उत्सुक।
ताड डोनघे

2
प्रदर्शन के मामले के रूप में। शब्दार्थ यह एक संरचना का उपयोग करने के लिए और अधिक समझ में आता है क्योंकि केवल प्रत्येक क्षेत्र के मामलों का मूल्य और संदर्भ पहचान अप्रासंगिक है, 30 या तो फ़ील्ड कॉपी करने के लिए अधिक है (कहते हैं कि वे ज्यादातर संदर्भ प्रकार हैं; 32-बिट पर 120bytes और 240bytes) 64) एक वर्ग (4 या 8 बाइट्स) के साथ की तुलना में। हालांकि, संरचना की कॉपी-बाय-वैल्यू प्रकृति का मतलब है कि एक बार कॉपी किए जाने के बाद एक संदर्भ प्रकार के साथ तुलना में तेजी से हो रहा है, इसलिए थ्रेशोल्ड जहां संरचना कम कुशल है, 1-पॉइंटर-आकार से अधिक है, जो ऊपर की ओर जोर देता है। > 4 पॉइंटर-साइज़ पर विचार करने के लिए इसका समय।
जॉन हैना

बहुत बढ़िया। स्पष्टीकरण के लिए धन्यवाद! :)
टाड डोनाघे

3

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


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

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

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

3

हो सकता है कि C # 4.0 का वैकल्पिक और नामित पैरामीटर इसका एक अच्छा विकल्प हो?

वैसे भी, आप जिस विधि का वर्णन कर रहे हैं, वह प्रोग्राम व्यवहार को अमूर्त करने के लिए भी अच्छा हो सकता है। उदाहरण के लिए, आप SaveImage(ImageSaveParameters saveParams)एक इंटरफ़ेस में एक मानक-मानक हो सकते हैं जहां एक इंटरफ़ेस ImageSaveParametersभी है और छवि-प्रारूप के आधार पर अतिरिक्त पैरामीटर हो सकते हैं। उदाहरण के लिए JpegSaveParametersएक Quality-property है जबकि PngSaveParametersएक BitDepth-property है।

यह है कि पेंट.नेट में सेव सेव-डायलॉग ऐसा कैसे करता है, इसलिए यह एक बहुत ही वास्तविक जीवन उदाहरण है।


3

जैसा कि पहले कहा गया था: यह करने के लिए सही कदम है, लेकिन पालन पर भी विचार करें:

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

0

इतने सारे शानदार जवाब यहाँ। मैं अपने दो सेंट जोड़ना चाहूंगा।

पैरामीटर ऑब्जेक्ट एक अच्छी शुरुआत है। लेकिन और भी बहुत कुछ है जो किया जा सकता है। निम्नलिखित पर विचार करें (रूबी उदाहरण):

/ 1 / केवल सभी मापदंडों को समूहीकृत करने के बजाय, देखें कि क्या मापदंडों का सार्थक समूहन हो सकता है। आपको एक से अधिक पैरामीटर ऑब्जेक्ट की आवश्यकता हो सकती है।

def display_line(startPoint, endPoint, option1, option2)

बना सकता है

def display_line(line, display_options)

/ 2 / पैरामीटर वस्तु में मूल संख्या की तुलना में गुणों की संख्या कम हो सकती है।

def double_click?(cursor_location1, control1, cursor_location2, control2)

बना सकता है

def double_click?(first_click_info, second_click_info) 
                       # MouseClickInfo being the parameter object type 
                       # having cursor_location and control_at_click as properties

इस तरह के उपयोग आपको इन पैरामीटर ऑब्जेक्ट्स में सार्थक व्यवहार जोड़ने की संभावनाओं की खोज करने में मदद करेंगे। आप पाएंगे कि वे अपनी प्रारंभिक डेटा क्लास गंध को आपके आराम के लिए जल्द ही हिला देते हैं। : -)

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