2011-12-29 6 views
41

पर तर्कों की संख्या को कम करना मैं "स्वच्छ कोड" पढ़ रहा हूं और मुझे अपने कुछ कार्यों (आमतौर पर कन्स्ट्रक्टर) को अपने अधिकतम 3 पैरामीटर में रखने के तरीके को समझने में परेशानी हो रही है।एक निर्माता

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

उदाहरण के तौर पर, मेरे पास "MovablePatch" कक्षा है। यह उपयोगकर्ता को विंडो में चारों ओर एक वर्ग खींचने देता है। इसे त्रिज्या, रंग, रेंडरर, प्रारंभिक संरचना, और दृश्यता सहित कई मानकों की आवश्यकता है। वर्तमान में मैं अपने जीयूआई से इन सब को इकट्ठा करने और फिर कहते हैं:

MovablePatch(int radius, Renderer* renderer, Color color, Position initial, bool visibility) 

ये केवल चीजें हैं जो मैं इस वर्ग में जरूरत से कुछ हैं। क्या कोई सुझाव दे सकता है कि मैं इस जानकारी को कन्स्ट्रक्टर को पास करने के लिए कैसे पैकेज कर सकता हूं? मुझे कोई स्पष्ट "छोटे वर्गों में तोड़ने" दिखाई नहीं देता है।

+7

बिल्डर पैटर्न को देखो। – Bashwork

+1

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

+6

संबंधित गुणों के लिए एक सरल 'संरचना' का उपयोग करने के लिए पारित किया जाना चाहिए क्योंकि एक जन्म पैरामीटर मेरे जन्म से पहले किया गया है, मुझे पूरा यकीन है। – AJG85

उत्तर

31

आप

MovablePatch(Renderer* renderer, CircleAppearance circleAppearance) 

जहां CircleAppearance बटोरता अन्य जानकारी हो सकता था।

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

सबसे महत्वपूर्ण बात यह है कि आप इसके बारे में सोच रहे हैं और चीजों को अच्छी और साफ रखने की कोशिश कर रहे हैं! :)

20

कुछ चीजें जिन्हें आप पास कर रहे हैं उन्हें बड़े निर्माण में समझा जा सकता है। उदाहरण के लिए, visibility, color, और radius, आपके द्वारा परिभाषित किसी ऑब्जेक्ट में रखा जा सकता है। फिर, इस वर्ग का एक उदाहरण, इसे ColoredCircle पर कॉल करें, MovablePatch के निर्माता में पारित किया जा सकता है। एक रंगीन सर्कल परवाह नहीं है कि यह कहां है या यह किस रेंडरर का उपयोग कर रहा है, लेकिन एक MovablePatch करता है।

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

+2

क्या यह केवल समस्या को स्थानांतरित नहीं करता है? आपको किसी भी तरह से 'रंगीन सर्कल' वर्ग को प्रारंभ करना होगा, और अभी भी चार पैरामीटर शेष हैं ... – MartinStettner

+2

@ मार्टिनस्टेटनर, हां आपको पहले 'रंगीन सर्कल' शुरू करना होगा, लेकिन यह पैरामीटर में से चार होना चाहिए। इसका मतलब है कि 'मूवबल पैच' केवल 'रंगीन सर्कल' और 'रेंडरर *' लेगा। –

+1

पैच में या मंडल में 'स्थिति' को संग्रहित किया जाना चाहिए? मुझे लगता है कि पैच की स्थिति है, सर्कल नहीं। –

8

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

आपके मामले में, आपको एक नया MovablePatchBuilder क्लास मिलेगा।

दृष्टिकोण बहुत उपयोगी है और आप इसे कई अलग-अलग ढांचे और भाषाओं में पा सकते हैं।

कुछ उदाहरण देखने के लिए here देखें।

12

Named Parameter Idiom यहां उपयोगी है।आपके मामले में, आप

class PatchBuilder 
{ 
public: 
    PatchBuilder() { } 
    PatchBuilder& radius(int r) { _radius = r; return *this; } 
    PatchBuilder& renderer(Renderer* r) { _renderer = r; return *this; } 
    PatchBuilder& color(const Color& c) { _color = c; return *this; } 
    PatchBuilder& initial(const Position& p) { _position = p; return *this; } 
    PatchBuilder& visibility(bool v) { _visibility = v; return *this; } 

private: 
    friend class MovablePatch; 
    int _radius; 
    Renderer* _renderer; 
    Color _color; 
    Position _position; 
    bool _visibility; 
}; 

class MovablePatch 
{ 
public: 
    MovablePatch(const PatchBuilder& b) : 
     _radius(b._radius); 
     _renderer(b._renderer); 
     _color(b._color); 
     _position(b._position); 
     _visibility(b._visibility); 
    { 

    } 

private: 
    int _radius; 
    Renderer* _renderer; 
    Color _color; 
    Position _position; 
    bool _visibility; 
}; 

तो आप ऐसा

int 
main() 
{ 
    MovablePatch foo = PatchBuilder(). 
     radius(1.3). 
     renderer(asdf). 
     color(asdf). 
     position(asdf). 
     visibility(true) 
    ; 
} 

ज्यादा सरल की तरह उपयोग हो सकता है, लेकिन मैं इसे भर में बिंदु हो जाता है लगता है। कुछ मापदंडों के लिए आवश्यक हैं अगर वे PatchBuilder निर्माता में शामिल किया जा सकता है:

class PatchBuilder 
{ 
public: 
    PatchBuilder(const Foo& required) : _foo(required) { } 
    ... 
}; 

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

+1

मैंने 'वापसी * ​​इस' कथन को 'पैचबिल्डर' के तरीकों में जोड़ने की स्वतंत्रता ली;) ... – MartinStettner

+11

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

+1

@AdamDymitruk मैंने आपके सुझाव के आधार पर कुछ शब्द के साथ जवाब अपडेट किया है। –

28

चेहरे के मूल्य पर "आपके रचनाकारों में 3 से अधिक पैरामीटर नहीं" जैसे अधिकतम मत लें। यदि आपके पास ऑब्जेक्ट अपरिवर्तनीय बनाने का मामूली मौका है, तो इसे बनाएं; और यदि यह अपरिवर्तनीय है तो इसका मतलब है कि यह 50 पैरामीटर के साथ एक कन्स्ट्रक्टर होगा, तो यह हो; इसके लिए जाओ; इसके बारे में दो बार भी मत सोचो।

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

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

+7

+1। अपरिवर्तनीयता छोटी पैरामीटर सूचियों की तुलना में कहीं अधिक फायदेमंद है। – vocaro

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

  • कोई संबंधित समस्या नहीं^_^