क्या "सूखा सिद्धांत" का उल्लंघन "विरासत पर रचना" है?


36

उदाहरण के लिए, विचार करें कि मेरा विस्तार करने के लिए अन्य वर्गों के लिए एक वर्ग है:

public class LoginPage {
    public String userId;
    public String session;
    public boolean checkSessionValid() {
    }
}

और कुछ उपवर्ग:

public class HomePage extends LoginPage {

}

public class EditInfoPage extends LoginPage {

}

वास्तव में, उपवर्ग में ओवरराइड करने के लिए कोई विधि नहीं है, मैं भी होमपेज़ को जेनेरिक तरीके से एक्सेस नहीं करूँगा, अर्थात: मैं ऐसा कुछ नहीं करूँगा:

for (int i = 0; i < loginPages.length; i++) {
    loginPages[i].doSomething();
}

मैं सिर्फ लॉगिन पृष्ठ का पुन: उपयोग करना चाहता हूं। लेकिन https://stackoverflow.com/a/53354 के अनुसार , मुझे यहां रचना पसंद करनी चाहिए क्योंकि मुझे इंटरफ़ेस लॉगिन की आवश्यकता नहीं है, इसलिए मैं यहाँ विरासत का उपयोग नहीं करता हूं:

public class HomePage {
    public LoginPage loginPage;
}

public class EditInfoPage {
    public LoginPage loginPage;
}

लेकिन समस्या यहाँ आती है, नए संस्करण में, कोड:

public LoginPage loginPage;

जब एक नया वर्ग जोड़ा जाता है तो डुप्लिकेट करता है। और अगर LoginPage को सेटर और गेट्टर की जरूरत है, तो अधिक कोड कॉपी करने की आवश्यकता है:

public LoginPage loginPage;

private LoginPage getLoginPage() {
    return this.loginPage;
}
private void setLoginPage(LoginPage loginPage) {
    this.loginPage = loginPage;
}

तो मेरा सवाल यह है कि, "सूखा सिद्धांत" का उल्लंघन "विरासत पर रचना" है?


13
कभी-कभी आपको न तो विरासत की आवश्यकता होती है और न ही रचना की, जो यह कहना है कि कभी-कभी कुछ वस्तुओं के साथ एक वर्ग काम करता है।
एरिक Eidt

23
आप अपने सभी पृष्ठों को लॉगिन पृष्ठ क्यों बनाना चाहेंगे? हो सकता है कि बस एक लॉगिन पृष्ठ हो।
श्री कोच

29
लेकिन, विरासत के साथ, आपने extends LoginPageसभी जगह नकल की है। चेक दोस्त!
el.pescado

2
यदि आपको आखिरी स्निपेट में समस्या है, तो आप गेटर्स और सेटरों का उपयोग कर सकते हैं। वे इनकैप्सुलेशन का उल्लंघन करते हैं।
ब्रायन मैककिनटन

4
इसलिए, अपने पृष्ठ को सजाने में सक्षम होने के लिए और अपने LoginPageडेकोरेटर बनाने के लिए । कोई और अधिक दोहराव, बस एक सरल page = new LoginPage(new EditInfoPage())और आप कर रहे हैं। या आप प्रमाणीकरण मॉड्यूल बनाने के लिए खुले-बंद-सिद्धांत का उपयोग करते हैं जिसे किसी भी पृष्ठ पर गतिशील रूप से जोड़ा जा सकता है। कोड दोहराव से निपटने के लिए बहुत सारे तरीके हैं, जिसमें मुख्य रूप से एक नया अमूर्त खोजना शामिल है। LoginPageएक बुरा नाम है, जिसे आप यह सुनिश्चित करना चाहते हैं कि उपयोगकर्ता उस पृष्ठ को ब्राउज़ करते समय प्रमाणित किया जाता है, जबकि LoginPageवह नहीं होने पर एक उचित त्रुटि संदेश को रीडायरेक्ट या दिखाया जाता है।
पॉलीग्नोम

जवाबों:


46

एर प्रतीक्षा आप चिंतित हैं कि दोहरा रहे हैं

public LoginPage loginPage;

दो स्थानों पर DRY का उल्लंघन? उस तर्क से

int x;

अब पूरे कोड बेस में केवल एक ही वस्तु में मौजूद हो सकता है। Bleh।

DRY ध्यान में रखने के लिए एक अच्छी बात है, लेकिन चलो। के अतिरिक्त

... extends LoginPage

अपने विकल्प में डुप्लिकेट हो रहा है तो भी DRY के बारे में गुदा होने का मतलब यह नहीं है।

मान्य DRY चिंताएँ कई स्थानों पर परिभाषित किए जाने वाले समान स्थानों में आवश्यक समान व्यवहार पर ध्यान केंद्रित करती हैं, जैसे कि इस व्यवहार को बदलने की आवश्यकता कई स्थानों पर परिवर्तन की आवश्यकता होती है। एक स्थान पर निर्णय लें और आपको उन्हें केवल एक ही स्थान पर बदलना होगा। इसका मतलब यह नहीं है कि केवल एक वस्तु कभी भी आपके लॉगिनपेज का संदर्भ रख सकती है।

सूखी आँख बंद करके पालन नहीं किया जाना चाहिए। यदि आप नकल कर रहे हैं क्योंकि कॉपी और पेस्ट एक अच्छा तरीका या वर्ग नाम सोचने से ज्यादा आसान है तो आप शायद गलत हैं।

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

कोड क्या दिखता है DRY बस के बारे में नहीं है। यह विचारहीन पुनरावृत्ति के साथ एक विचार के विवरण को चारों ओर नहीं फैलाने के बारे में है, जिसमें निर्धारक पुनरावृत्ति का उपयोग करके चीजों को ठीक करने के लिए बनाए रखने के लिए मजबूर करता है। यह तब होता है जब आप अपने आप को यह बताने की कोशिश करते हैं कि नासमझी की पुनरावृत्ति सिर्फ आपका अधिवेशन है जो कि चीजें वास्तविक बुरे तरीके से होती हैं।

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

लेकिन हाँ, यह बहुत से अतिरिक्त कीबोर्ड टाइपिंग है। जब तक मैं कोड को पढ़ता हूं तब तक मैं एक उछाल के नीचे और नीचे उछल -कूद की यो-यो समस्या को रोक सकता हूं ।

अब ऐसा नहीं है कि मैं कभी विरासत का इस्तेमाल करने से इनकार करता हूं। मेरा एक पसंदीदा उपयोग अपवादों को नया नाम देना है:

public class MyLoginPageWasNull extends NullPointerException{}

int x;एक कोडबेस में शून्य से अधिक बार मौजूद नहीं हो सकता है
। एलन बेट्स


... मुझे पता था कि आप प्वाइंट क्लास के साथ पीछे हटने वाले हैं। प्वाइंट क्लास की परवाह किसी को नहीं है। अगर मैं आपके कोडबेस में जाऊंगा और देखूंगा तो int a; int b; int x;मुझे 'आप' को हटाने के लिए धक्का लगेगा।
। एलन बेट्स

@ K.AlanBates वाह। यह दुखद है कि आप सोचते हैं कि इस तरह का व्यवहार आपको एक अच्छा कोडर बना देगा। सबसे अच्छा कोडर वह नहीं है जो दूसरों के बारे में सबसे ज्यादा चीजें पा सके। यह एक है जो बाकी को बेहतर बनाता है।
कैंडिड_ओरेंज

अर्थहीन नामों का उपयोग करना गैर-स्टार्टर है और संभावना उस कोड के डेवलपर को संपत्ति के बजाय एक दायित्व बनाती है।
। एलन बेट्स

127

DRY सिद्धांत के साथ एक आम गलतफहमी यह है कि यह किसी भी तरह कोड की पंक्तियों को नहीं दोहराने से संबंधित है। DRY सिद्धांत है "ज्ञान के हर टुकड़े में एक प्रणाली के भीतर एक एकल, अस्पष्ट, आधिकारिक प्रतिनिधित्व होना चाहिए" । यह ज्ञान के बारे में है, कोड के बारे में नहीं।

LoginPageलॉग इन करने के लिए पृष्ठ को कैसे खींचना है इसके बारे में जानता है। यदि यह EditInfoPageपता है कि यह कैसे करना है तो इसका उल्लंघन होगा। LoginPageरचना के माध्यम से शामिल करना किसी भी तरह से DRY सिद्धांत का उल्लंघन नहीं है।

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


27
"एकल जिम्मेदारी सिद्धांत" का बहुत अधिक दुरुपयोग किया जाता है। "अपने आप को दोहराएं" आसानी से नंबर दो में आ सकता है :-)
gnasher729

28
"DRY" "डोंट रिपिट योरसेल्फ" के लिए एक आसान परिचित है जो एक कैच वाक्यांश है, लेकिन सिद्धांत का नाम नहीं है, सिद्धांत का वास्तविक नाम "वंस एंड ओनली वन्स" है, जो बदले में एक आकर्षक नाम है एक सिद्धांत के लिए जो वर्णन करने के लिए पैराग्राफ की एक जोड़ी लेता है। महत्वपूर्ण बात पैराग्राफ के जोड़े को समझ रही है, तीन अक्षरों D, R, और Y को याद नहीं करना
Jörg W Mittag

4
@ gnasher729 आप जानते हैं, मैं वास्तव में आपसे सहमत हूं कि एसआरपी का शायद अधिक दुरुपयोग किया जाता है। हालांकि निष्पक्ष होने के लिए, कई मामलों में मुझे लगता है कि वे अक्सर एक साथ दुरुपयोग कर रहे हैं। मेरा सिद्धांत यह है कि सामान्य रूप से प्रोग्रामर को "आसान नामों" के साथ शब्दकूटों पर भरोसा नहीं करना चाहिए।

17
IMHO यह एक अच्छा जवाब है। हालांकि, निष्पक्ष होना: मेरे अनुभव के लिए, DRY उल्लंघन का सबसे अक्सर रूप कॉपी-पेस्ट प्रोग्रामिंग और बस डुप्लिकेट कोड के कारण होता है। किसी ने मुझे एक बार कहा था "जब भी आप किसी कोड को कॉपी-पेस्ट करने जा रहे हों, तो दो बार सोचें कि क्या डुप्लिकेट किए गए हिस्से को एक सामान्य फ़ंक्शन में नहीं निकाला जा सकता है" - जो कि IMHO बहुत अच्छी सलाह थी।
डॉक ब्राउन

9
कॉपी-पेस्ट का दुरुपयोग निश्चित रूप से DRY के उल्लंघन के लिए एक प्रेरणा शक्ति है, लेकिन बस कॉपी-पेस्ट के लिए मना करना DRY का पालन करने के लिए खराब मार्गदर्शन है। जब समान तरीके ज्ञान के विभिन्न टुकड़ों का प्रतिनिधित्व करते हैं तो मुझे समान कोड वाले दो तरीकों के लिए कोई पछतावा नहीं होगा। वे दो अलग-अलग जिम्मेदारियां निभाते हैं। उनके पास आज समान कोड होने के लिए होता है। उन्हें स्वतंत्र रूप से बदलने के लिए स्वतंत्र होना चाहिए। हां, ज्ञान, कोड नहीं। अच्छे से कहा। मैंने अन्य उत्तरों में से एक लिखा है, लेकिन मैं इस पर झुकूंगा। +1।
कैंडिड_ऑरेंज

12

संक्षिप्त उत्तर: हां, यह करता है - कुछ मामूली, स्वीकार्य डिग्री के लिए।

पहली नज़र में, वंशानुक्रम कभी-कभी आपको कोड की कुछ पंक्तियों को बचा सकता है, क्योंकि इसमें यह कहने का प्रभाव होता है कि "मेरे पुन: उपयोग करने वाले वर्ग में 1: 1 तरीके से सभी सार्वजनिक विधियाँ और विशेषताएँ होंगी"। इसलिए यदि किसी घटक में 10 विधियों की सूची है, तो किसी को विरासत में मिली श्रेणी में उन्हें दोहराना नहीं है। जब एक संरचना परिदृश्य में उन 10 विधियों में से 9 को पुन: उपयोग करने वाले घटक के माध्यम से सार्वजनिक रूप से उजागर किया जाना चाहिए, तो किसी को 9 प्रतिनिधि कॉलिंग लिखना होगा, और शेष एक को बाहर जाने देना चाहिए, इसके आसपास कोई रास्ता नहीं है।

यह क्यों सहनीय है? उन विधियों को देखें, जो एक संरचना परिदृश्य में दोहराई जाती हैं - ये विधियाँ विशेष रूप से घटक के इंटरफ़ेस पर कॉल को सौंप रही हैं, इसलिए इसमें कोई वास्तविक तर्क नहीं है।

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

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

आपके उदाहरण के लिए एक नोट: मुझे नहीं पता कि आपका HomePageऔर आपका EditInfoPageलुक कैसा है, लेकिन अगर उनके पास लॉगिन कार्यक्षमता है, और HomePage(या EditInfoPage) ए है LoginPage , तो विरासत यहाँ सही उपकरण हो सकता है। एक कम बहस का उदाहरण, जहां रचना अधिक स्पष्ट तरीके से बेहतर उपकरण होगी, शायद चीजों को स्पष्ट कर देगी।

यह मानते हुए कि न तो कोई है , और न HomePageही बाद वाले को फिर से उपयोग करना चाहता है, जैसा कि आपने लिखा है, इससे यह बहुत संभावना है कि किसी को केवल कुछ के कुछ हिस्सों की आवश्यकता होती है । यदि ऐसा है, तो दिखाए गए तरीके से रचना का उपयोग करने की तुलना में बेहतर दृष्टिकोण हो सकता हैEditInfoPageLoginPageLoginPage

  • LoginPageअपने स्वयं के घटक में पुन: प्रयोज्य भाग को निकालें

  • उस घटक का पुन: उपयोग करें HomePageऔर EditInfoPageउसी तरह इसका उपयोग अब अंदर किया जाता हैLoginPage

इस तरह, यह आम तौर पर बहुत स्पष्ट हो जाएगा कि क्यों और कब वंशानुक्रम पर रचना सही दृष्टिकोण है।

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