क्या एकाधिक उत्तराधिकार एकल उत्तरदायित्व सिद्धांत का उल्लंघन करता है?


18

यदि आपके पास एक वर्ग है जो दो अलग-अलग वर्गों से विरासत में मिला है, तो इसका मतलब यह नहीं है कि आपका उपवर्ग स्वचालित रूप से (कम से कम) 2 चीजें करता है, प्रत्येक सुपरक्लास से एक?

मेरा मानना ​​है कि यदि आपके पास कई इंटरफ़ेस विरासत हैं, तो कोई अंतर नहीं है।

संपादित करें: स्पष्ट होने के लिए, मेरा मानना ​​है कि यदि कई वर्ग उपवर्ग एसआरपी का उल्लंघन करते हैं, तो कई (गैर-मार्कर या बुनियादी इंटरफ़ेस (जैसे तुलनीय)) को लागू करना एसआरपी का भी उल्लंघन करता है।


बस स्पष्ट होने के लिए, आप यह भी मानते हैं कि कई इंटरफेस को लागू करना एसआरपी का उल्लंघन करता है?

मेरा मानना ​​है कि यदि कई वर्ग उपवर्ग एसआरपी का उल्लंघन करते हैं, तो कई (गैर-मार्कर) इंटरफेस को लागू करना एसआरपी का भी उल्लंघन करता है।
m3th0dman 17

मैं इस प्रश्न को बढ़ाऊंगा, लेकिन आपने उस प्रश्न में अपनी राय लिख दी है, जिससे मैं सहमत नहीं हूं।
निकोल

1
@ नाइक: मैंने अपनी राय नहीं कही है (आपको उपरोक्त टिप्पणी पढ़नी चाहिए); मैं इसे और अधिक स्पष्ट करने के लिए प्रश्न को संपादित करूंगा।
m3th0dman

1
@ नैक मेरे पास एक राय नहीं है, इसीलिए मैंने पूछा। मैंने केवल यह कहा था कि दोनों संबंधित हैं (इंटरफ़ेस विरासत और वर्ग विरासत); यदि यह वर्ग वंशानुक्रम का उल्लंघन करता है तो यह इंटरफ़ेस वंशानुक्रम के लिए भी उल्लंघन करता है, यदि यह एक के लिए नहीं होता है और न ही यह दूसरे के लिए उल्लंघन करता है। और मुझे अप वोट की परवाह नहीं है ...
m3th0dman

जवाबों:


17

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

आप अपनी कक्षाओं और इंटरफेस को दो प्रमुख समूहों में विभाजित कर सकते हैं - आपके सिस्टम की आवश्यक जटिलता को संबोधित करने वाले, और इसके आकस्मिक जटिलता को संबोधित करने वाले। यदि एक से अधिक "आवश्यक जटिलता" वर्गों से विरासत में मिली, तो यह खराब है; यदि आपको एक "आवश्यक" और एक या अधिक "आकस्मिक" वर्गों से विरासत में मिला है, तो यह ठीक है।

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

class BillingCycleInvoice : public BillingCycle, public Invoice {
};

यह बुरा है: आपकी BillingCycleInvoiceएक मिश्रित जिम्मेदारी है क्योंकि यह सिस्टम की आवश्यक जटिलता से संबंधित है।

दूसरी ओर, यदि आप इस तरह के वारिस हैं

class PersistentInvoice : public Invoice, public PersistentObject {
};

आपकी कक्षा ठीक है: तकनीकी रूप से, यह एक ही बार में दो चिंताओं की सेवा करता है, लेकिन चूंकि उनमें से केवल एक ही आवश्यक है, आप आकस्मिक को "व्यवसाय करने की लागत" के रूप में विरासत में लिख सकते हैं।


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

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

9

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

सॉफ्टवेयर डिजाइन विज्ञान की तरह ही कला है, यह कई प्रतिस्पर्धी हितों का संतुलन बनाने वाला कार्य है। हमारे पास उन चीजों से बचने में मदद करने के लिए नियम हैं जिन्हें हम जानते हैं कि एक दिशा में दूर हैं जो समस्याएं पैदा करती हैं, लेकिन वे नियम हमें आसानी से एक ऐसी जगह पर ले जा सकते हैं जो पहले की तुलना में खराब या बदतर है, जो हम पहले से बचने की कोशिश कर रहे थे।


4

कुछ हद तक। एसआरपी के मुख्य सिद्धांत पर ध्यान दें:

एक वर्ग को बदलने का केवल एक कारण होना चाहिए।

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

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


2

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

इसका मतलब यह नहीं है कि कक्षा में तीन जिम्मेदारियां हैं। इसका मतलब है कि उपयोगकर्ता को मॉडल करने की जिम्मेदारी के हिस्से को क्रमबद्धता और दृढ़ता का समर्थन करने की आवश्यकता है।


2

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

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


1

मुझे लगता है कि यह इस बात पर निर्भर करता है कि आप कैसे जिम्मेदारी को परिभाषित करते हैं। क्लासिक iostream उदाहरण में यह SRP का उल्लंघन नहीं करता है। IOstream एक द्विदिश धारा के प्रबंधन के लिए जिम्मेदार है।

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

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