2011-11-10 19 views
78

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

+0

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

+0

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

+17

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

उत्तर

74

यह एक अच्छा विचार है। उदाहरण के लिए डब्ल्यूसीएफ में डेटा अनुबंध कैसे किया जाता है।

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

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

ग्रेट। मैं इस धारणा के तहत था कि संपत्तियों के साथ एक वर्ग होने और कोई विधि बेकार नहीं थी। – Xaisoft

+0

अच्छा दूसरा बिंदु। – Xaisoft

+2

यदि इसमें केवल डेटा सदस्य होंगे, तो मैं इसे संरचना बनाना पसंद करता हूं। संरचना का उपयोग इंप्रेशन देता है कि यह सिर्फ डेटा है। – Yousf

10

एक उत्कृष्ट विचार और समस्या के लिए एक बहुत ही आम समाधान है कि:

डेविड हेफेरनान का उल्लेख है, यह स्वयं दस्तावेज़ कोड कर सकते हैं। 2 या 3 से अधिक पैरामीटर वाले तरीके तेजी से समझने के लिए कठिन और कठिन हो जाते हैं।

यह सब एक एकल कक्षा में Encapsulating बहुत स्पष्ट कोड बनाता है। स्वाभाविक रूप से जब आप मानकों का एक बहुत कुछ है

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

स्थितीय identication के आधार पर वैकल्पिक बस भयंकर है: क्योंकि अपने गुण नाम है तो आप इस तरह स्वयं का दस्तावेजीकरण कोड लिख सकते हैं।

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

+1

एक उत्तर में महान और उत्कृष्ट यकीन है कि मुझे अब अच्छा महसूस कर रहा है। – Xaisoft

3

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

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

+0

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

+0

उन क्षेत्रों के लिए structs की अनुशंसा नहीं की जाती है –

+0

डेविड क्यों? फ़ील्ड की संख्या के साथ क्या करना है? बस उत्सुक। एक प्रदर्शन मामले के रूप में –

5

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

62

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

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

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

इस पर कुछ अधिक विचारों के लिए How many parameters are too many? देखें।

+0

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

+12

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

+0

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

9

मार्टिन फाउलर अपनी पुस्तक में रिफैक्टरिंग में Introduce Parameter Object पर कॉल करता है। कि प्रशस्ति पत्र के साथ, कुछ यह एक बुरा विचार कहेंगे।

+1

हाँ, लेकिन 30 पैरामीटर के लिए, कहीं और गलत है जिसे पहले – manojlds

+1

@manojlds को ठीक करना होगा: दरअसल, लेकिन आपको कहीं भी शुरू करना होगा ... –

14

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

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

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

+0

फीचर ईर्ष्या के लिए +1 अच्छा जवाब। – RedFilter

25

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

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

+4

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

3

Plain Old Data कक्षा का उपयोग करना उचित हो सकता है चाहे आप रिफैक्टरिंग कर रहे हों या नहीं। मैं उत्सुक हूं कि आपने क्यों सोचा कि यह नहीं हो सकता है।

+0

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

+0

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

+0

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

3

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

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

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

3

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

  • अपने विधि बहुत जटिल हो सकता है (आप इसे एक में बदल जाते हैं और अधिक तरीकों में विभाजित पर विचार करना चाहिए, या यहाँ तक अलग वर्ग)
  • अगर आप मापदंडों के लिए वर्ग बनाने के लिए, यह immutable
  • यदि पैरामीटर के कई अशक्त हो सकता है या कुछ डिफ़ॉल्ट मान हो सकता था, तो आप अपने वर्ग के लिए builder pattern उपयोग कर सकते हैं बनाते हैं।
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 

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

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