2012-04-04 16 views
7

अस्वीकरण: मैं इस परियोजना पर dependency injection का उपयोग करने की प्यार और बोर्ड भर में एक शिथिल युग्मित इंटरफ़ेस आधारित डिजाइन के लिए होता है, लेकिन निर्भरता इंजेक्शन के उपयोग इस परियोजना में मार गिराया गया है। इसके अलावा SOLID डिज़ाइन सिद्धांत (और design patterns सामान्य रूप से) कुछ विदेशी हैं जहां मैं काम करता हूं और मैं उनमें से कई के लिए नया हूं। इसलिए इस समस्या के लिए बेहतर डिज़ाइन का सुझाव देते समय इसे पर विचार करें।क्या कोई बेहतर डिज़ाइन विकल्प है?

यहां कोड का एक सरलीकृत संस्करण है जिस पर मैं काम कर रहा हूं, और ऐसा लगता है कि यह प्रतीत होता है। यदि ऐसा है तो मैं क्षमा चाहता हूं। निम्नलिखित वर्गों पर विचार करें:

// foo referenced and used in one part of code 
    var foo = new Foo(); 
    foo.Operation2(); // or foo.Operation1(); 

    // some other point in the program where we don't have a reference to foo 
    // but do have a reference to the helper 
    helper.DoSomethingHelpful(); 

हालांकि मैं अब यह पता लगाना है कि मैं भी foo.Operation1 प्रदर्शन करने की जरूरत है:

// Foo is a class that wraps underlying functionality from another 
// assembly to create a simplified API. Think of this as a service layer class, 
// a facade-like wrapper. It contains a helper class that is specific to 
// foo. Other AbstractFoo implementations have their own helpers. 

public class Foo : AbstractFoo 
{ 
    private readonly DefaultHelper helper; 
    public override DefaultHelper Helper { get { return helper; } } 

    public Foo() 
    { 
     helper = new Helper("custom stuff"); 
    } 

    public override void Operation1(string value) 
    { 
     Console.WriteLine("Operation1 using " + value); 
    } 

    public override void Operation2() 
    { 
     Console.WriteLine("Operation2"); 
    } 
} 

// Helper derives from a default implementation and allows us to 
// override it's methods to do things specific for the class that 
// holds this helper. Sometimes we use a custom helper, sometimes 
// we use the default one. 

public class Helper : DefaultHelper 
{ 
    private readonly string customStuff; 

    public Helper(string value) 
    { 
     customStuff = value; 
    } 

    public override void DoSomethingHelpful() 
    { 
     Console.WriteLine("I was helpful using " + customStuff); 
    } 
} 

इन दोनों वर्ग इस प्रकार उपयोग किया जाता है कहो helper.DoSomethingHelpful(); के कुछ कार्यान्वयन? संभावित कामकाज मैंने सोचा था:

  1. फू और सहायक के पास एक द्विपक्षीय संबंध है। ताकि DoSomethingHelpful में हम foo.Operation2 कॉल कर सकते हैं
  2. foo IHelp इंटरफ़ेस को लागू और foo में "सहायक" कोड के लिए कदम
  3. उपयोग प्रतिनिधिमंडल और विधि Operation2 हेल्पर के निर्माता में एक Action<string> प्रतिनिधि के रूप में पारित किया है। इन तरीकों का

कोई भी आदर्श होने लगते हैं (हालांकि मैं काफी यह फ़ैसला किया है मैं विकल्प 1 पसंद नहीं है और विकल्प के साथ रख-रखाव के बारे में चिंतित हूँ 3 अगर हम पता लगाने के बाद हम पास करनी होगी अधिक प्रतिनिधियों में)। इससे मुझे आश्चर्य होता है कि Helper/Foo कॉम्बो के प्रारंभिक डिज़ाइन में कोई समस्या है या नहीं। विचार?

+0

मुझे लगता है कि आप 'DefualtHelper' के बजाय' DefaultHelper' का मतलब है। – ja72

+0

@ ja72, वर्तनी कभी मेरा मजबूत सूट नहीं था, मैंने इस टाइपो को अपडेट किया है। अस्वीकरण के लिए – Matt

+1

+1 ... एक बड़ी हंसी थी। – scottheckel

उत्तर

1

"इन तरीकों में से कोई भी आदर्श होने लगते हैं (हालांकि मैं बहुत ज्यादा है निर्धारित मैं विकल्प 1 पसंद है और विकल्प 3 के साथ रख-रखाव के बारे में चिंतित हूँ अगर हम पता लगाने के बाद हम में पारित करने के लिए की जरूरत नहीं है अधिक प्रतिनिधियों) इससे मुझे आश्चर्य होता है कि हेल्पर/फू कॉम्बो के प्रारंभिक डिजाइन में कोई समस्या है। "

आप बिल्कुल सही हैं - हेल्पर और फू के डिजाइन में कोई समस्या है। प्रारंभिक रूप से वर्णित मूल फू/हेल्पर रिलेशनशिप ठीक है, और यह एक आम पैटर्न है जब आपको अन्य ऑब्जेक्ट्स को लपेटना होता है जिन्हें आप नियंत्रित नहीं करते हैं। लेकिन तब आप कहते हैं:

"क्या होगा यदि मुझे पता है कि मैं भी helper.DoSomethingHelpful() में से कुछ कार्यान्वयन में foo.Operation1 प्रदर्शन करने की जरूरत है ;?"

यह वह जगह है जहां हमें कोई समस्या है। आपने एक रिश्ते का वर्णन करना शुरू किया जहां फू हेल्पर पर निर्भर है; अब आप एक रिश्ते का वर्णन कर रहे हैं जहां हेल्पर फू पर निर्भर है। वह तुरंत मुझे बताता है कि आपके निर्भरता संबंध उलझ गए हैं। वस्तुओं के बीच निर्भरता संबंध केवल एक ही रास्ता जाना चाहिए; वास्तव में निर्भरता इंजेक्शन इस पर निर्भर करता है।

+0

+1 मैं यहां सहमत हूं और यह पहचानने के लिए धन्यवाद कि मुझे विकल्प 1 और 3 (यानी उलझन में निर्भरता) क्यों पसंद नहीं आया। और मुझे लगता है कि इस मामले में फू और हेल्पर की कार्यक्षमता को संयोजित करने से उनकी परस्पर निर्भरता के कारण समझ में आता है। IHelp इंटरफ़ेस का उपयोग करके मैं अभी भी फू का इलाज कर सकता हूं जैसे कि यह कोड में कहीं और सहायक है। – Matt

1

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

संपादित करें: ने "भविष्य के लिए डिज़ाइन न करने का प्रयास करें" बदल दिया क्योंकि ऐसा लगता है कि मैं क्या कहना चाहता हूं।सवाल में

संपादित करें फिर से कारण परिवर्तन

तुम बहुत कुछ इस तरह कर सकते हैं:

helper.DoSomethingUsefulWith(foo); 

तो अपने सहायक विधि निर्भरता यह क्रम में की जरूरत प्राप्त होगा काम करने के लिए

+0

भविष्य के लिए डिज़ाइन न करने का प्रयास करें? मैं समझता हूं कि आप क्या कहने की कोशिश कर रहे थे, लेकिन आम तौर पर मुझे नहीं लगता कि यह बहुत अच्छी सलाह है। –

+0

इसे डिज़ाइन करें ताकि इसे बनाए रखा जा सके और बढ़ाया जा सके: हाँ !!! कार्यक्षमता को जोड़ना अगर इसे बाद में जरूरी हो: नहीं !!! मैं यही कहने की कोशिश करता हूं :)। मुझे लगता है कि मैंने – ivowiblo

+0

@ivowiblo के लिए सबसे अच्छे शब्दों को नहीं चुना है, मैंने अपना प्रश्न अपडेट किया क्योंकि यह वास्तव में "क्या होगा" स्थिति नहीं है। यह एक आवश्यकता है जिसे मैं अब पार कर चुका हूं। मुझे और अधिक स्पष्ट होना चाहिए था। माफ़ कीजिये। – Matt

3

कैसे एक आकस्मिक ("उपयोग") संबंध के बारे में:

public class Helper : DefaultHelper 
{ 
    private readonly string customStuff; 

    public Helper(string value) 
    { 
     customStuff = value; 
    } 

    public override void DoSomethingHelpful(AbstractFoo foo) 
    { 
     foo.Operation1(); 
     Console.WriteLine("I was helpful using " + customStuff);   
    } 
} 

तो आप उचित Foo कार्यान्वयन के संदर्भ की अपेक्षा करने के लिए अमूर्त सहायक को संशोधित करते हैं।

+1

यूएमएल में, यह [निर्भरता] है (http://publib.boulder.ibm.com/infocenter/rtnlhelp/v6r0m0/index.jsp?topic=%2Fcom.ibm.xtools.modeler.doc%2Ftopics%2Fcdepend। एचटीएमएल) या "उपयोग" संबंध – SwDevMan81

+0

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

+0

@ मैट: क्या आप चाहते हैं कि 'BooHelper' को' बू 'तक पहुंच हो, वैसे ही आप' FooHelper' को 'Foo' तक पहुंच प्राप्त करना चाहते हैं या नहीं? आपकी टिप्पणी ने मुझे वास्तव में भ्रमित कर दिया। – ja72

1

मुझे लगता है कि आपके सभी समाधान अच्छे हैं; वे सिर्फ अलग-अलग क्षमताओं की पेशकश करते हैं। ये मतभेद अब बहुत ज्यादा मायने रखते हैं लेकिन भविष्य में होने की संभावना है।

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

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

+0

+1 मैं इंटरफ़ेस दृष्टिकोण से सहमत हूं और फू और हेल्पर के संयोजन की संभावना तीनों में से बेहतर है और क्या मैंने इसे जाने का फैसला किया है। – Matt

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