बहुत अधिक अमूर्त बनाना कोड का विस्तार करना मुश्किल है


9

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

अनिवार्य रूप से, इस कोडबेस में बहुत सी एब्स्ट्रैक्शन कोड डुप्लीकेशन को कम करने में मदद करती है, लेकिन जब वे उच्चतम एब्स्ट्रैक्शन लेने के लिए बनाई जाती हैं, तो यह विस्तार / बदलते तरीकों को कठिन बना देती है। मुझे इस तरह की स्थिति में क्या करना चाहिए? मैं दोष के लिए केंद्र में हूं, हालांकि हर कोई इस बात पर सहमत नहीं हो सकता है कि वे क्या अच्छा मानते हैं, इसलिए यह अंत में मुझे नुकसान पहुंचा रहा है।


10
"समस्या" को अनपढ़ करने के लिए एक कोड नमूना जोड़ें, स्थिति को और अधिक समझने में मदद करेगा
सीबेकिट

मुझे लगता है कि यहां दो SOLID सिद्धांत हैं। सिंगल रिस्पांसिबिलिटी - यदि आप एक बूलियन में एक फ़ंक्शन को पास करते हैं जिसे माना जाता है कि यह व्यवहार को नियंत्रित करता है, तो फ़ंक्शन की अब एक भी जिम्मेदारी नहीं होगी। अन्य एक Liskov प्रतिस्थापन सिद्धांत है। कल्पना कीजिए कि एक फ़ंक्शन है जो पैरामीटर के रूप में कक्षा ए में लेता है। यदि आप A के बजाय कक्षा B में पास होते हैं, तो क्या उस फ़ंक्शन की कार्यक्षमता टूट जाएगी?
बोबेक

मुझे संदेह है कि ए विधि बहुत लंबी है और एक से अधिक काम करती है। क्या यह मामला है?
राड 80

जवाबों:


27

अगर मैं B को अलग तरीके से संभालने के लिए एक नया तरीका बनाने की कोशिश करता हूं, तो उसे कोड डुप्लीकेशन के लिए बुलाया जाता है।

सभी कोड दोहराव समान नहीं बनाए गए हैं।

कहें कि आपके पास एक विधि है जो दो मापदंडों को लेती है और उन्हें एक साथ बुलाया जाता है total()। कहते हैं कि आपके पास एक और एक है add()। उनके कार्यान्वयन पूरी तरह से समान दिखते हैं। क्या उन्हें एक विधि में विलय कर दिया जाना चाहिए? नहीं!!!

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

DRY (खुद को न दोहराएं) सिद्धांत बताता है:

ज्ञान के हर टुकड़े में एक प्रणाली के भीतर एक एकल, अस्पष्ट, आधिकारिक प्रतिनिधित्व होना चाहिए।

wiki.c2.com - अपने आप को दोहराएं नहीं

लेकिन DRY को एक समान कार्यान्वयन की तलाश में कोड को स्कैन करने की आदत में दूषित किया जा सकता है जो ऐसा लगता है कि यह कहीं और की कॉपी और पेस्ट है। यह DRY का मस्तिष्क मृत रूप है। नरक, आप एक स्थैतिक विश्लेषण उपकरण के साथ ऐसा कर सकते हैं। यह मदद नहीं करता है क्योंकि यह DRY के बिंदु को अनदेखा करता है जो कि कोड को लचीला बनाए रखना है।

यदि मेरी कुल आवश्यकताएं बदल जाती हैं तो मुझे अपना totalकार्यान्वयन बदलना पड़ सकता है । इसका मतलब यह नहीं है कि मुझे अपना addकार्यान्वयन बदलने की आवश्यकता है । अगर कुछ गुबरैला उन्हें एक साथ एक विधि से मिटा देता है, तो मैं अब थोड़े से अनावश्यक दर्द में हूँ।

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

तो मेरी सलाह है कि इसी तरह के कोड को घुटने के झटके से रोकने के लिए अपने कोडबेस को समुद्री मील में बाँध दें। मैं यह नहीं कह रहा हूं कि आप इस तथ्य को अनदेखा करने के लिए स्वतंत्र हैं कि विधियाँ मौजूद हैं और इसके बजाय विली नीली को कॉपी और पेस्ट करें। नहीं, प्रत्येक विधि में एक अच्छा नाम होना चाहिए जो उस विचार का समर्थन करता है जो इसके बारे में है। यदि इसका कार्यान्वयन किसी अन्य अच्छे विचार के कार्यान्वयन से मेल खाने के लिए होता है, तो, आज, नरक की परवाह कौन करता है?

दूसरी ओर, यदि आपके पास एक ऐसी sum()विधि है जिसमें एक समान या यहां तक ​​कि अलग-अलग कार्यान्वयन है total(), फिर भी कभी-कभी आपकी कुल आवश्यकताओं को बदलने के लिए आपको बदलना पड़ता है sum()तो एक अच्छा मौका है ये दो अलग-अलग नामों के तहत एक ही विचार हैं। न केवल कोड अधिक लचीला होगा यदि उन्हें विलय कर दिया गया था, तो यह उपयोग करने के लिए कम भ्रमित नहीं होगा।

बूलियन मापदंडों के लिए, हाँ यह एक बुरा कोड गंध है। इतना ही नहीं नियंत्रण प्रवाह एक समस्या है, बदतर यह दिखा रहा है कि आप एक बुरे बिंदु पर एक अमूर्त में काट दिया है। सार चीजों को उपयोग करने के लिए सरल बनाना है, न कि अधिक जटिल। अपने व्यवहार को नियंत्रित करने के लिए एक विधि से बूल पास करना एक गुप्त भाषा बनाने जैसा है जो यह तय करता है कि आप वास्तव में किस पद्धति को बुला रहे हैं। ओउ! मेरे लिए ऐसा मत करो। प्रत्येक विधि को अपना नाम दें जब तक कि आपके पास चल रहे पॉलीमॉर्फिज़्म के लिए कुछ ईमानदार न हों ।

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

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

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

वह अमूर्तन है। ग्राहक के रूप में मुझे भी नहीं पता कि मैं किससे बात कर रहा हूं। मुझे सिर्फ इतना पता है कि मुझे इससे क्या चाहिए। अगर इसका मतलब है कि आपको इसके ठीक करने से पहले इसके इंटरफेस को बदलने के लिए कुछ लपेटना होगा। मुझे परवाह नहीं है। बस वही करो जो मुझे चाहिए। इसे जटिल बनाना बंद करो।

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

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

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

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


मैं तहे दिल से सहमत हूं। DRY तीन-शब्द-कैचफ्रेज़ डोन्ट रिपीट योरसेल्फ के लिए एक तीन-अक्षर-संक्षिप्त है, जो विकी पर 14 पृष्ठ के लेख के बदले है । यदि आप सभी करते हैं और 14 पेज के लेख को पढ़े और समझे बिना उन तीन अक्षरों को आँख बंद करके देख रहे हैं, तो आप मुश्किल में पड़ जाएंगे । यह एक बार और केवल एक बार (OAOO) से अधिक निकटता से जुड़ा है और अधिक एकल बिंदु सत्य (SPOT) / सत्य के एकल स्रोत (SSOT) से संबंधित है
डब्ल्यू पर Jörg W Mittag

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

@ JörgWMittag बेशक। जरूरी चीज है विचार। यदि आप अलग-अलग दिखने वाले कोड के साथ विचार को दोहरा रहे हैं तो आप अभी भी सूखे का उल्लंघन कर रहे हैं।
कैंडिड_ऑरेंज सेप

मुझे एक 14 पृष्ठ के लेख की कल्पना करनी चाहिए, जो खुद को नहीं दोहराता है, वह खुद को बहुत दोहराता है।
चक एडम्स

7

सामान्य कहावत है कि हम सब यहाँ और वहाँ पढ़ते हैं:

अमूर्त की एक और परत जोड़कर सभी समस्याओं को हल किया जा सकता है।

खैर, यह सच नहीं है! आपका उदाहरण इसे दिखाता है। इसलिए मैं थोड़ा संशोधित कथन प्रस्तावित करूँगा (पुन: उपयोग के लिए स्वतंत्र महसूस; ;-)):

अमूर्त के सही स्तर का उपयोग करके हर समस्या को हल किया जा सकता है।

आपके मामले में दो अलग-अलग समस्याएं हैं:

  • ओवर-सामान्यीकरण सार स्तर पर हर विधि जोड़ने की वजह से;
  • ठोस व्यवहार के विखंडन से बड़ी तस्वीर न मिलने और खो जाने का अहसास होता है। विंडोज़ इवेंट लूप में थोड़ा सा।

दोनों कोष्ठबद्ध हैं:

  • यदि आप एक ऐसी विधि को अमूर्त करते हैं जहाँ हर विशेषज्ञता इसे अलग तरीके से करती है, तो सब कुछ ठीक है। किसी को भी यह समस्या नहीं है कि एक विशेष तरीके से Shapeइसकी गणना की जा सकती है surface()
  • यदि आप कुछ ऑपरेशन को अमूर्त करते हैं जहाँ एक सामान्य सामान्य व्यवहार पैटर्न है, तो आपके पास दो विकल्प हैं:

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

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

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


5

जब भी मैं एक ऐसी विधि देखता हूं जहां व्यवहार अपने पैरामीटर के प्रकार पर स्विच करता है, तो मैं तुरंत पहले विचार करता हूं कि क्या वह विधि वास्तव में विधि पैरामीटर पर है। उदाहरण के लिए, इसके बजाय एक विधि की तरह:

public void sort(List values) {
    if (values instanceof LinkedList) {
        // do efficient linked list sort
    } else { // ArrayList
        // do efficient array list sort
    }
}

मैं यह करूँगा:

values.sort();

// ...

class ArrayList {
    public void sort() {
        // do efficient array list sort
    }
}

class LinkedList {
    public void sort() {
        // do efficient linked list sort
    }
}

हम व्यवहार को उस स्थान पर ले जाते हैं जो जानता है कि इसका उपयोग कब करना है। हम एक वास्तविक अमूर्त बनाते हैं जहाँ आपको प्रकार या कार्यान्वयन के विवरण को जानने की आवश्यकता नहीं है। आपकी स्थिति के लिए, इस विधि को मूल वर्ग (जिसे मैं कॉल करूंगा O) से टाइप करने Aऔर इसे ओवरराइड करने के लिए स्थानांतरित करने के लिए अधिक समझदारी हो सकती है B। यदि विधि को doItकिसी वस्तु पर बुलाया जाता है , तो अलग-अलग व्यवहार के साथ स्थानांतरित doItकरें Aऔर ओवरराइड करें B। यदि doItमूल रूप से कहा जाता है, जहां से डेटा बिट्स हैं , या यदि विधि का उपयोग पर्याप्त स्थानों पर किया जाता है, तो आप मूल विधि और प्रतिनिधि को छोड़ सकते हैं:

class O {
    int x;
    int y;

    public void doIt(A a) {
        a.doIt(this.x, this.y);
    }
}

हम हालांकि थोड़ा गहरा गोता लगा सकते हैं। आइए इसके बजाय एक बूलियन पैरामीटर का उपयोग करने के सुझाव को देखें और देखें कि हम आपके सहकर्मी के सोचने के तरीके के बारे में क्या सीख सकते हैं। उनका प्रस्ताव है:

public void doIt(A a, boolean isTypeB) {
    if (isTypeB) {
        // do B stuff
    } else { 
        // do A stuff
    }
}

यह instanceofमेरे पहले उदाहरण में उपयोग किए गए एक बहुत बड़ा लग रहा है, सिवाय इसके कि हम उस चेक को बाहरी कर रहे हैं। इसका मतलब है कि हमें इसे दो में से एक तरीके से कॉल करना होगा:

o.doIt(a, a instanceof B);

या:

o.doIt(a, true); //or false

पहले तरीके से, कॉल पॉइंट का कोई पता नहीं है कि Aइसका क्या प्रकार है। इसलिए, क्या हमें पूरे रास्ते में बूलियंस को पास करना चाहिए? क्या यह वास्तव में एक पैटर्न है जो हम सभी कोड बेस पर चाहते हैं? यदि कोई तीसरा प्रकार है, तो हमें क्या करना चाहिए? यदि इस प्रकार विधि को कहा जाता है, तो हमें इसे प्रकार में ले जाना चाहिए और सिस्टम को हमारे लिए बहुरूपिक रूप से कार्यान्वयन का चयन करने देना चाहिए।

दूसरा तरीका में, हम पहले से ही पता होना चाहिए के प्रकार के aकॉल बिंदु पर। आमतौर पर इसका मतलब है कि हम या तो वहाँ उदाहरण बना रहे हैं, या पैरामीटर के रूप में उस प्रकार का उदाहरण ले रहे हैं। Oउस पर एक विधि बनाना Bयहाँ काम करेगा। कंपाइलर को पता होगा कि किस विधि को चुनना है। जब हम इस तरह के बदलावों से गुजर रहे होते हैं, तो नकल गलत अमूर्तता पैदा करने से बेहतर है , कम से कम जब तक हम यह पता नहीं लगाते हैं कि हम वास्तव में कहां जा रहे हैं। बेशक, मैं सुझाव दे रहा हूं कि हम वास्तव में कोई फर्क नहीं पड़ता कि हमने इस बिंदु पर क्या बदल दिया है।

हमें Aऔर के बीच के संबंधों को और करीब से देखने की जरूरत है B। आमतौर पर, हमें बताया जाता है कि हमें विरासत पर रचना का पक्ष लेना चाहिए । यह हर मामले में सच नहीं है, लेकिन यह मामलों की एक आश्चर्य की बात संख्या में सच है एक बार हम में खुदाई। Bसे विरासत में मिली Aहै, जिसका अर्थ हमें विश्वास है कि, Bएक है ABबस ऐसे ही इस्तेमाल किया जाना चाहिए A, सिवाय इसके कि यह थोड़ा अलग तरीके से काम करता है। लेकिन वे अंतर क्या हैं? क्या हम मतभेदों को अधिक ठोस नाम दे सकते हैं? क्या यह Bएक नहीं है A, लेकिन वास्तव Aमें ऐसा Xहै A'या हो सकता है B'? अगर हमने ऐसा किया तो हमारा कोड कैसा दिखेगा?

यदि हमने पहले बताए अनुसार विधि को आगे बढ़ाया है A, तो हम एक उदाहरण के रूप Xमें इंजेक्ट कर सकते हैं A, और उस विधि को Xनिम्न पर सौंप सकते हैं :

class A {
    X x;
    A(X x) {
        this.x = x;
    }

    public void doIt(int x, int y) {
        x.doIt(x, y);
    }
}

हम लागू कर सकते हैं A'और B', और छुटकारा पा सकते हैं B। हमने एक अवधारणा को एक नाम देकर कोड में सुधार किया है जो संभवतः अधिक अंतर्निहित हो सकता है, और खुद को संकलन समय के बजाय उस व्यवहार को रनटाइम पर सेट करने की अनुमति देता है। Aवास्तव में कम अमूर्त भी बन गया है। एक विस्तारित विरासत संबंध के बजाय, यह एक प्रत्यायोजित वस्तु पर कॉलिंग विधि है। वह वस्तु अमूर्त है, लेकिन कार्यान्वयन में अंतर पर अधिक केंद्रित है।

हालांकि देखने के लिए एक आखिरी चीज है। आइए अपने सहकर्मी के प्रस्ताव पर वापस जाएं। यदि सभी कॉल साइटों पर हम स्पष्ट रूप से जानते हैं कि Aहमारे पास किस प्रकार का है, तो हमें कॉल करना चाहिए जैसे:

B b = new B();
o.doIt(b, true);

हमने पहले यह मान लिया था कि कंपोजिंग में ऐसा Aहै जो या Xतो है । लेकिन शायद यह धारणा भी सही नहीं है। क्या यह एकमात्र ऐसी जगह है जहां इस और मामलों के बीच अंतर है? अगर ऐसा है, तो शायद हम थोड़ा अलग तरीका अपना सकते हैं। हमारे पास अभी भी ऐसा है जो या तो है , लेकिन यह संबंधित नहीं है । केवल इसके बारे में परवाह है, तो चलो केवल इसे पास करें :A'B'ABXA'B'AO.doItO.doIt

class O {
    int x;
    int y;

    public void doIt(A a, X x) {
        x.doIt(a, x, y);
    }
}

अब हमारी कॉल साइट इस तरह दिखती है:

A a = new A();
o.doIt(a, new B'());

एक बार फिर Bगायब हो जाता है, और अमूर्त अधिक ध्यान केंद्रित में चला जाता है X। हालांकि, यह समय Aकम जानकर भी सरल है। यह और भी कम सार है।

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


1
यह मुझे चौंकाता है कि जो उदाहरण "बुरा" कोड आप यहां दे रहे हैं, वह उसी तरह का है जैसा मैं गैर-ओओ भाषा में करना चाहूंगा। मुझे आश्चर्य है कि क्या उन्होंने गलत पाठ सीखा और उन्हें ओओ दुनिया में लाए जिस तरह से वे कोड करते हैं?
बाल्ड्रिक

1
@ बेल्ड्रिक प्रत्येक प्रतिमान अपने अनूठे फायदे और नुकसान के साथ, सोचने के अपने तरीके लाता है। कार्यात्मक हास्केल में, पैटर्न मिलान बेहतर दृष्टिकोण होगा। हालांकि इस तरह की भाषा में, मूल समस्या के कुछ पहलू संभव नहीं होंगे।
cbojar

1
यह सही जवाब है। एक विधि जो इसके द्वारा संचालित प्रकार के आधार पर कार्यान्वयन को बदलती है, उस प्रकार की एक विधि होनी चाहिए।
रोमन रेपर

0

वंशानुक्रम द्वारा अमूर्तता काफी बदसूरत हो सकती है। विशिष्ट कारखानों के साथ समानांतर श्रेणी पदानुक्रम। रिफैक्टरिंग एक सिर-दर्द बन सकता है। और बाद में विकास, वह स्थान जहां आप हैं।

वहाँ एक विकल्प मौजूद है: विस्तार के बिंदु , सख्त अमूर्तता के, और स्तरीय अनुकूलन। एक विशिष्ट शहर के लिए उस अनुकूलन के आधार पर सरकारी ग्राहकों का एक अनुकूलन कहें।

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

विस्तार योग्य ऑब्जेक्ट बेस क्लास होल्ड एक्सटेंशन होने से यह विस्तार कार्य करता है:

void f(CreditorBO creditor) {
    creditor.as(AllowedCreditorBO.class).ifPresent(allowedCreditor -> ...);
}

आंतरिक रूप से विस्तार वर्ग द्वारा विस्तारित वस्तुओं के लिए वस्तु का एक आलसी मानचित्रण है।

जीयूआई वर्गों और घटकों के लिए समान विस्तार, आंशिक रूप से विरासत के साथ। बटन जोड़ना और ऐसे।

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

इसलिए वर्तमान संदर्भ में काम करने का कोई उपाय नहीं है।


0

too हिडन फ्लो कंट्रोल ’मुझे भी बहुत सुरीली लगती है।
संदर्भ से बाहर किए गए किसी भी निर्माण या तत्व में वह विशेषता हो सकती है।

सार अच्छा है। मैं उन्हें दो दिशानिर्देशों के साथ गुस्सा करता हूं:

  • जल्द ही अमूर्त नहीं करना बेहतर है। गर्भपात से पहले पैटर्न के अधिक उदाहरणों की प्रतीक्षा करें। 'अधिक' निश्चित रूप से व्यक्तिपरक और उस स्थिति के लिए विशिष्ट है जो कठिन है।

  • एब्सट्रैक्शन के कई स्तरों से बचें क्योंकि एब्सट्रैक्शन अच्छा है। एक प्रोग्रामर को नए या परिवर्तित कोड के लिए उन स्तरों को अपने सिर में रखना होगा क्योंकि वे कोडबेस को डुबोते हैं और 12 स्तरों को गहरा करते हैं। अच्छी तरह से अमूर्त कोड की इच्छा इतने सारे स्तरों को जन्म दे सकती है कि वे कई लोगों के लिए कठिन हैं। यह भी 'निंजा केवल बनाए रखा' कोडबेस की ओर जाता है।

दोनों मामलों में 'अधिक और बहुत अधिक' निश्चित संख्याएँ नहीं हैं। निर्भर करता है। वही इसे कठिन बनाता है।

संडी मेट्ज़ का यह लेखन मुझे भी पसंद है

https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction

दोहराव दूर गलत अमूर्त से सस्ता है
और
गलत अमूर्त से अधिक दोहराव पसंद करते हैं

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