इंटरफ़ेस अलगाव सिद्धांत की दो विरोधाभासी परिभाषाएँ - कौन सी सही है?


14

ISP पर लेख पढ़ते समय, ISP की दो विरोधाभासी परिभाषाएं प्रतीत होती हैं:

पहली परिभाषा (देखें 1 , 2 , 3 ) के अनुसार, आईएसपी कहता है कि इंटरफ़ेस को लागू करने वाले वर्गों को उन कार्यात्मकताओं को लागू करने के लिए मजबूर नहीं किया जाना चाहिए जिनकी उन्हें आवश्यकता नहीं है। इस प्रकार, वसा इंटरफ़ेसIFat

interface IFat
{
     void A();
     void B();
     void C();
     void D();
}

class MyClass: IFat
{ ... }

छोटे इंटरफेस में विभाजित किया जाना चाहिए ISmall_1औरISmall_2

interface ISmall_1
{
     void A();
     void B();
}

interface ISmall_2
{
     void C();
     void D();
}

class MyClass:ISmall_2
{ ... }

इस तरह से मेरे MyClassही तरीकों इसकी आवश्यकता है (लागू करने में सक्षम है D()और C()मजबूर किया जा रहा भी के लिए डमी कार्यान्वयन प्रदान करने के लिए बिना,) A(), B()और C():

लेकिन दूसरी परिभाषा के अनुसार ( 1 , 2 , Nazar Merza द्वारा उत्तर देखें ), आईएसपी कहता है कि MyClientकॉलिंग विधियों को MyServiceउन तरीकों के बारे में पता नहीं होना चाहिए , जिनकीMyService उसे आवश्यकता नहीं है। दूसरे शब्दों में, यदि MyClientकेवल C()और D()इसके बजाय, की कार्यक्षमता की आवश्यकता है

class MyService 
{
    public void A();
    public void B();
    public void C();
    public void D();
}

/*client code*/      
MyService service = ...;
service.C(); 
service.D();

हमें ग्राहक-विशिष्ट इंटरफेस MyService'sमें तरीकों को अलग करना चाहिए :

public interface ISmall_1
{
     void A();
     void B();
}

public interface ISmall_2
{
     void C();
     void D();
}

class MyService:ISmall_1, ISmall_2 
{ ... }

/*client code*/
ISmall_2 service = ...;
service.C(); 
service.D();

इस प्रकार, पूर्व परिभाषा के साथ, ISP का लक्ष्य " IFat इंटरफ़ेस को लागू करने वाली कक्षाओं का जीवन आसान बनाना है ", जबकि बाद वाले ISP का लक्ष्य " MyService के तरीकों को आसान बनाने वाले ग्राहकों के जीवन को आसान बनाना " है।

आईएसपी की दो अलग-अलग परिभाषाओं में से कौन सी वास्तव में सही है?

@MARJAN VENEMA

1।

तो जब आप IFat को छोटे इंटरफ़ेस में विभाजित करने जा रहे हैं, तो कौन से तरीके समाप्त होते हैं, जिसमें ISmallinterface को यह तय करना चाहिए कि सदस्य कितने सामंजस्यपूर्ण हैं।

हालांकि यह एक ही इंटरफ़ेस के भीतर एक सुसंगत तरीकों को रखने के लिए समझ में आता है, मैंने सोचा कि आईएसपी पैटर्न के साथ क्लाइंट की जरूरतों को एक इंटरफ़ेस के "सामंजस्य" पर पूर्वता लेना चाहिए। दूसरे शब्दों में, मैंने सोचा था कि आईएसपी के साथ हमें उसी इंटरफ़ेस के भीतर गांठ लगाना चाहिए, जो विशेष क्लाइंट्स के लिए आवश्यक हैं, भले ही इसका मतलब है कि उस इंटरफ़ेस से बाहर निकलकर उन तरीकों को जो सामंजस्य के लिए चाहिए, उन्हें भी उसी इंटरफ़ेस के अंदर रखा जाना चाहिए?

इस प्रकार, अगर बहुत सारे क्लाइंट थे जिन्हें केवल कॉल करने की आवश्यकता होगी CutGreens, लेकिन यह भी नहीं GrillMeat, तो आईएसपी पैटर्न का पालन करने के लिए हमें केवल CutGreensअंदर रखना चाहिए ICook, लेकिन यह भी नहीं GrillMeat, भले ही दो विधियां अत्यधिक सामंजस्यपूर्ण हों ?!

2।

मुझे लगता है कि आपका भ्रम पहली परिभाषा में छिपी धारणा से उपजा है: कि कार्यान्वयन कक्षाएं पहले से ही एकल जिम्मेदारी सिद्धांत का पालन कर रही हैं।

"एसआरपी का पालन नहीं करने वाली कक्षाएं लागू करने से" क्या आप उन कक्षाओं का जिक्र कर रहे हैं जो लागू होते हैं IFatया उन कक्षाओं में लागू होते हैं जो ISmall_1/ लागू होते हैं ISmall_2? मुझे लगता है कि आप उन कक्षाओं का उल्लेख कर रहे हैं जो लागू होते हैं IFat? यदि हां, तो आप यह क्यों मानते हैं कि वे पहले से ही एसआरपी का पालन नहीं करते हैं।

धन्यवाद


4
ऐसी कई परिभाषाएँ क्यों नहीं हो सकती हैं जो दोनों एक ही सिद्धांत द्वारा परोसी गई हैं?
बोबसन

5
ये परिभाषाएं एक-दूसरे का खंडन नहीं करती हैं।
माइक पार्टरिज

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

2
दूसरी परिभाषा को लागू करने वालों की परवाह नहीं है। यह कॉलर्स के दृष्टिकोण से इंटरफेस को परिभाषित करता है और इस बारे में कोई धारणा नहीं बनाता है कि कार्यान्वयनकर्ता पहले से मौजूद हैं या नहीं। यह शायद मानता है कि जब आप आईएसपी का पालन करते हैं और उन इंटरफेस को लागू करने के लिए आते हैं, तो आप निश्चित रूप से उन्हें बनाते समय एसआरपी का पालन करें।
मार्जन वेनेमा

2
आप पहले से कैसे जानते हैं कि ग्राहक क्या मौजूद होंगे और उन्हें किन तरीकों की आवश्यकता होगी? आप नहीं कर सकते। हाथ से पहले क्या आप जान सकते हैं कि आपका इंटरफ़ेस कितना सामंजस्यपूर्ण है।
ट्यूलेंस कोर्डोवा

जवाबों:


6

दोनों सही हैं

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

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

पहली परिभाषा जो आप उल्लेख करते हैं, वह कार्यान्वयनकर्ताओं पर केंद्रित है, दूसरी क्लाइंट पर। जो, @ user61852 के विपरीत, मैं इंटरफ़ेस के उपयोगकर्ताओं / कॉलर्स के रूप में लेता हूं, कार्यान्वयनकर्ताओं के लिए नहीं।

मुझे लगता है कि आपका भ्रम पहली परिभाषा में छिपी धारणा से उपजा है: कि कार्यान्वयन कक्षाएं पहले से ही एकल जिम्मेदारी सिद्धांत का पालन कर रही हैं।

मेरे लिए दूसरी परिभाषा, इंटरफ़ेस के कॉल करने वाले ग्राहकों के साथ, इच्छित लक्ष्य तक पहुंचने का एक बेहतर तरीका है।

अलग-अलग रखने

अपने प्रश्न में आप कहते हैं:

इस तरह से मेरा MyClass केवल उन विधियों को लागू करने में सक्षम है जो इसे (D () और C ()) की आवश्यकता के बिना, A (), B () और C () के लिए डमी कार्यान्वयन प्रदान करने के लिए मजबूर किए बिना:

लेकिन वह दुनिया को उलटा कर रहा है।

  • एक इंटरफ़ेस लागू करने वाला वर्ग यह निर्धारित नहीं करता है कि जिस इंटरफ़ेस को वह लागू कर रहा है, उसमें उसकी क्या ज़रूरत है।
  • इंटरफेस तय करते हैं कि एक क्रियान्वयन वर्ग को क्या तरीके प्रदान करने चाहिए।
  • एक इंटरफ़ेस के कॉलर वास्तव में हैं जो यह निर्धारित करते हैं कि उनके लिए प्रदान करने के लिए इंटरफ़ेस को किस कार्यक्षमता की आवश्यकता है और इस प्रकार एक कार्यान्वयनकर्ता को क्या प्रदान करना चाहिए।

इसलिए जब आप IFatछोटे इंटरफ़ेस में विभाजित करने जा रहे हैं , तो कौन से तरीके समाप्त होते हैं, जिसमें ISmallइंटरफ़ेस को यह तय करना चाहिए कि सदस्य कितने सामंजस्यपूर्ण हैं।

इस इंटरफ़ेस पर विचार करें:

interface IEverythingButTheKitchenSink
{
     void DoDishes();
     void CleanSink();
     void CutGreens();
     void GrillMeat();
}

आप किन तरीकों से डालेंगे ICookऔर क्यों? क्या आप CleanSinkएक साथ GrillMeatसिर्फ इसलिए लगाएंगे क्योंकि आपके पास एक ऐसा वर्ग है जो सिर्फ और सिर्फ एक-दो चीजें करता है, लेकिन अन्य तरीकों की तरह कुछ भी नहीं है? या क्या आप इसे दो और समकालिक इंटरफेस में विभाजित करेंगे, जैसे:

interface IClean
{
     void DoDishes();
     void CleanSink();
}

interface ICook
{
     void CutGreens();
     void GrillMeat();
}

इंटरफ़ेस घोषणा नोट

एक अंतरफलक परिभाषा अधिमानतः एक अलग इकाई में अपने दम पर होनी चाहिए, लेकिन अगर यह बिल्कुल कॉलर या कार्यान्वयनकर्ता के साथ रहने की आवश्यकता है, तो यह वास्तव में कॉलर के साथ होना चाहिए। अन्यथा कॉलर को कार्यान्वयनकर्ता पर तत्काल निर्भरता मिलती है जो इंटरफेस के उद्देश्य को पूरी तरह से हरा रहा है। यह भी देखें: बेस क्लास जैसी ही फाइल में इंटरफेस की घोषणा करना, क्या यह एक अच्छा अभ्यास है? प्रोग्रामर पर और हमें उन वर्गों के साथ इंटरफेस क्यों रखना चाहिए जो उन्हें लागू करने के बजाय उनका उपयोग करते हैं? StackOverflow पर।


1
क्या आप मेरे द्वारा किए गए अपडेट को देख सकते हैं?
एडविरज

"फोन करने वाले को कार्यान्वयनकर्ता पर तत्काल निर्भरता मिलती है " ... केवल यदि आप डीआईपी (निर्भरता व्युत्क्रम सिद्धांत) का उल्लंघन करते हैं, यदि कॉलर आंतरिक चर, पैरामीटर, रिटर्न मान आदि प्रकार के ICookबजाय SomeCookImplementorडीआईपी जनादेश के रूप में है, तो यह नहीं है 'पर निर्भर नहीं रहना है SomeCookImplementor
ट्यूलेंस कोर्डोवा

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

मैंने इस प्रश्न प्रोग्रामर.स्टैकएक्सचेंज .com/a/ 271142 /61852 में आपके कोड उदाहरणों का फिर से उपयोग किया , इसे पहले से ही स्वीकार किए जाने के बाद इसमें सुधार किया गया। मैंने आपको उदाहरणों के लिए उचित श्रेय दिया।
ट्यूलेंस कोरडोवा

कूल @ user61852 :) (और क्रेडिट के लिए धन्यवाद)
मार्जन वेनेमा

14

आप "क्लाइंट" शब्द को एक ग्राहक के रूप में "क्लाइंट" के साथ चार दस्तावेजों के गैंग में उपयोग के रूप में भ्रमित करते हैं।

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

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

सिद्धांत की भावना "क्लाइंट" (इंटरफ़ेस को लागू करने वाला वर्ग) से बचने के लिए डमी विधियों को लागू करने के लिए होती है ताकि पूरे इंटरफ़ेस का पालन किया जा सके जब यह केवल संबंधित तरीकों के एक सेट की परवाह करता है।

इसके अलावा यह संभव के रूप में युग्मन की कम मात्रा होने का लक्ष्य रखता है ताकि एक ही स्थान पर किए गए परिवर्तन कम प्रभाव का कारण बनें। इंटरफेस को अलग करके आप युग्मन को कम करते हैं।

यह समस्या तब प्रकट होती है जब इंटरफ़ेस बहुत अधिक होता है और इसमें ऐसे तरीके होते हैं जिन्हें केवल एक के बजाय कई इंटरफेस में विभाजित किया जाना चाहिए।

आपके दोनों कोड उदाहरण ठीक हैं । यह केवल यह है कि दूसरे में आप "ग्राहक" का अर्थ है "एक वर्ग जो किसी अन्य वर्ग द्वारा दी जाने वाली सेवाओं / विधियों का उपभोग / कॉल करता है"।

मुझे आपके द्वारा दिए गए तीन लिंक में बताई गई अवधारणाओं में कोई विरोधाभास नहीं है।

बस स्पष्ट रखें कि "क्लाइंट" एसओएलआईडी टॉक में कार्यान्वयनकर्ता है


लेकिन @pdr के अनुसार, जबकि सभी लिंक में कोड उदाहरण ISP का पालन करते हैं, ISP परिभाषा "ग्राहक को अलग करने (एक वर्ग जो किसी अन्य वर्ग के तरीकों को कॉल करता है) को सेवा के बारे में अधिक जानने से" इसके बारे में "से अधिक है।" ग्राहकों (कार्यान्वयनकर्ताओं) से उन इंटरफेस को लागू करने के लिए मजबूर किया जा रहा है जिनका वे उपयोग नहीं करते हैं। "
एडवरसज

1
@EdvRusj मेरा जवाब ऑब्जेक्ट मेंटर (बॉब मार्टिन एंटरप्राइज) वेबसाइट में दस्तावेजों पर आधारित है, मार्टिन द्वारा खुद को रिटेन किया गया था जब वह चार के प्रसिद्ध गैंग में थे। जैसा कि आप जानते हैं कि फोर ऑफ ग्नॉग सॉफ्टवेयर इंजीनियरों का एक समूह था, जिसमें मार्टिन भी शामिल था, जिसने एसओएलआईडी के संक्षिप्त नाम को गढ़ा, सिद्धांतों की पहचान की और उनका दस्तावेजीकरण किया। docs.google.com/a/cleancoder.com/file/d/…
ट्यूलेंस कोरडोवा

तो आप @pdr से असहमत हैं और इस प्रकार आप ISP की पहली परिभाषा (मेरी मूल पोस्ट देखें) अधिक सहमत हैं?
एडविरज

@EdvRusj मुझे लगता है कि दोनों सही हैं। लेकिन दूसरा ग्राहक / सर्वर रूपक का उपयोग करके अनावश्यक भ्रम जोड़ता है। अगर मुझे एक का चयन करना है, तो मैं चार के आधिकारिक गैंग के साथ जाऊंगा, जो कि पहला है। लेकिन युग्मन और अनावश्यक निर्भरता को कम करने के लिए क्या महत्वपूर्ण है जो कि सभी के बाद SOLID सिद्धांतों की भावना है। इससे कोई फर्क नहीं पड़ता कि कौन सा सही है। महत्वपूर्ण बात यह है कि आपको व्यवहार को अलग करने के लिए इंटरफेस को अलग करना चाहिए। बस इतना ही। लेकिन जब संदेह होता है, तो मूल स्रोत पर जाएं।
ट्यूलेंस कोर्डोवा

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

5

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

पहली परिभाषा बहुत अधिक कसकर एलएसपी से जुड़ी हुई है।


3
ISP में, क्लाइंट्स को उन इंटरफ़ेस घटकों के लिए मजबूर नहीं किया जाना चाहिए जिनका वे उपयोग नहीं करते हैं। एलएसपी में, सेवाओं को विधि डी को लागू करने के लिए मजबूर नहीं किया जाना चाहिए क्योंकि कॉलिंग कोड के लिए विधि ए की आवश्यकता होती है। वे विरोधाभासी नहीं हैं, वे पूरक हैं।
पीडीआर

2
@EdvRusj, जो ग्राहक इंटरफेसए को लागू करता है, वह वास्तव में ग्राहक बी द्वारा आवश्यक इंटरफेस बी को लागू करने वाली सटीक वस्तु हो सकती है। दुर्लभ मामलों में जहां एक ही ग्राहक को अलग-अलग वर्गों के समान वस्तु को देखने की आवश्यकता होती है, कोड नहीं होगा। आमतौर पर "स्पर्श"। आप इसे एक उद्देश्य के लिए ए और दूसरे उद्देश्य के लिए बी के रूप में देख रहे होंगे।
एमी ब्लेंकशिप

1
@EdvRusj: यदि आप यहां इंटरफ़ेस की अपनी परिभाषा पर पुनर्विचार करते हैं तो यह मदद कर सकता है। यह हमेशा C # / Java शब्दों में इंटरफ़ेस नहीं है। आप इसके चारों ओर लिपटे कई सरल वर्गों के साथ एक जटिल सेवा कर सकते हैं, जैसे कि ग्राहक ए सेवा एक्स के साथ "इंटरफ़ेस" के लिए रैपर क्लास एएक्स का उपयोग करता है। इस प्रकार, जब आप एक्स को ए और एएक्स को प्रभावित करने वाले तरीके से बदलते हैं, तो आप नहीं होते हैं BX और B. को प्रभावित करने के लिए मजबूर
pdr

1
@EdvRusj: यह कहना अधिक सही होगा कि A और B परवाह नहीं करते हैं यदि वे X को कॉल कर रहे हैं या दोनों Y को कॉल कर रहे हैं और दूसरे को Z. THAT को ISP का मूल बिंदु बताया जा रहा है। तो आप चुन सकते हैं कि आप किस कार्यान्वयन के लिए जाते हैं, और बाद में आसानी से अपना मन बदल सकते हैं। ISP एक मार्ग या दूसरे का पक्ष नहीं लेता है, लेकिन LSP और SRP संभव है।
पीडीआर

1
@EdvRusj नहीं, ग्राहक A, सेवा X के साथ सेवा X को प्रतिस्थापित करने में सक्षम होगा, दोनों इंटरफ़ेस AX को लागू करेंगे। X और / या Y अन्य इंटरफेस को लागू कर सकते हैं, लेकिन जब क्लाइंट उन्हें AX के रूप में कहता है, तो यह उन अन्य इंटरफेस के बारे में परवाह नहीं करता है।
एमी ब्लेंकशिप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.