क्या एक दूसरे के संदर्भ में दो जावा 8 डिफ़ॉल्ट तरीकों को लागू करना अच्छा है?


14

मैं इसके समान दो संबंधित विधियों के साथ एक इंटरफ़ेस डिज़ाइन कर रहा हूं:

public interface ThingComputer {
    default Thing computeFirstThing() {
        return computeAllThings().get(0);
    }

    default List<Thing> computeAllThings() {
        return ImmutableList.of(computeFirstThing());
    }
}

लगभग आधे कार्यान्वयन केवल एक चीज की गणना करेंगे, जबकि अन्य आधे अधिक गणना कर सकते हैं।

क्या यह व्यापक रूप से उपयोग किए जाने वाले जावा 8 कोड में कोई मिसाल है? मुझे पता है कि हास्केल कुछ टाइपकास्ट में इसी तरह की चीजें करते हैं ( Eqउदाहरण के लिए)।

उल्टा यह है कि मुझे दो अमूर्त वर्ग ( SingleThingComputerऔर MultipleThingComputer) की तुलना में काफी कम कोड लिखना होगा ।

नकारात्मक पक्ष यह है कि एक खाली कार्यान्वयन संकलित करता है लेकिन रनटाइम के साथ उड़ता है StackOverflowError। एक के साथ पारस्परिक पुनरावृत्ति का पता लगाना संभव है ThreadLocalऔर एक अच्छाई त्रुटि दे सकता है, लेकिन यह गैर-छोटी गाड़ी कोड में ओवरहेड जोड़ता है।


3
आप कभी भी जान-बूझकर कोड को अनंत पुनरावृत्ति की गारंटी क्यों लिखेंगे? इससे अच्छा कुछ नहीं हो सकता।

1
वैसे यह "गारंटी" नहीं है; एक उचित कार्यान्वयन उन तरीकों में से एक को ओवरराइड करेगा।
तेवियन बार्न्स

6
आपको यह पता नहीं। एक वर्ग या इंटरफ़ेस को अपने दम पर खड़े होने की जरूरत है और यह नहीं मानें कि एक उपवर्ग प्रमुख तर्क त्रुटियों से बचने के लिए चीजों को एक निश्चित तरीके से करेगा। अन्यथा, यह भंगुर है और इसकी गारंटी तक नहीं रह सकती। ध्यान दें कि मैं नहीं कह रहा हूं कि आपका इंटरफ़ेस लागू करने वाले वर्ग को लागू कर सकता है throw new Error();या कुछ बेवकूफी कर सकता है, केवल यह कि इंटरफ़ेस मेंdefault विधियों के माध्यम से भंगुर अनुबंध नहीं होना चाहिए ।

मैं @Snowman से सहमत हूं, यह एक बारूदी सुरंग है। मुझे लगता है कि यह इस तरह से पाठ्यपुस्तक "बुराई कोड" है कि जॉन स्कीट का अर्थ है - ध्यान दें कि बुराई उतना ही बुरा नहीं है , यह दुष्ट / चालाक / आकर्षक है, लेकिन फिर भी गलत है :) मैं आपको सलाह देता हूं कि youtu.be/lGbQiguugcc?t=15m26s ( या वास्तव में, व्यापक संदर्भ के लिए पूरी बात - यह बहुत दिलचस्प है)।
कोनराड मोरावस्की

1
सिर्फ इसलिए कि प्रत्येक फ़ंक्शन को दूसरे के संदर्भ में परिभाषित किया जा सकता है , इसका मतलब यह नहीं है कि वे दोनों एक दूसरे के संदर्भ में परिभाषित किए जा सकते हैं। यह किसी भी भाषा में नहीं उड़ता है। आप 2 अमूर्त उत्तराधिकारियों के साथ एक इंटरफ़ेस चाहते हैं, प्रत्येक दूसरे के संदर्भ में एक को लागू करता है लेकिन दूसरे को अमूर्त करता है इसलिए कार्यान्वयनकर्ता चुनते हैं कि वे सही सार वर्ग से विरासत में किस पक्ष को लागू करना चाहते हैं। एक पक्ष को दूसरे से स्वतंत्र होना चाहिए, अन्यथा पॉप स्टैक जाता है । आपके पास पागल डिफॉल्ट हैं मानने वाले कार्यान्वयनकर्ता आपके लिए समस्या का समाधान करेंगे, उन्हें हल करने के abstractलिए मजबूर करने के लिए मौजूद हैं ।
जिमी हॉफ

जवाबों:


16

टीएल; डीआर: ऐसा न करें।

आप यहाँ जो दिखाते हैं वह भंगुर कोड है।

एक इंटरफ़ेस एक अनुबंध है। यह कहता है कि "चाहे आपको कोई भी वस्तु मिल जाए, वह X और Y कर सकता है।" जैसा कि लिखा गया है, आपका इंटरफ़ेस न तो एक्स और ही वाई करता है क्योंकि यह स्टैक ओवरफ्लो का कारण बनने की गारंटी है।

त्रुटि या उपवर्ग को फेंकना एक गंभीर त्रुटि को इंगित करता है जिसे पकड़ा नहीं जाना चाहिए:

एक त्रुटि थ्रोबल का एक उपवर्ग है जो गंभीर समस्याओं को इंगित करता है कि एक उचित अनुप्रयोग को पकड़ने की कोशिश नहीं करनी चाहिए।

इसके अलावा, VirtualMachineError , StackOverflowError के मूल वर्ग , यह कहते हैं:

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

आपका कार्यक्रम JVM संसाधनों से संबंधित नहीं होना चाहिए । जेवीएम का काम यही है। एक प्रोग्राम बनाना जो सामान्य ऑपरेशन के एक हिस्से के रूप में एक जेवीएम त्रुटि का कारण बनता है, खराब है। यह या तो आपके प्रोग्राम के क्रैश होने की गारंटी देता है, या इस इंटरफ़ेस के उपयोगकर्ताओं को उन त्रुटियों को फंसाने के लिए मजबूर करता है, जिनके साथ संबंध नहीं होना चाहिए।


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

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

स्रोत: सी ++ और निराशा के गड्ढे

StackOverflowErrorडिफॉल्ट रूप से एक इंटरफेस थ्रो करने से डेपेयर के गड्ढे में डेवलपर्स को धक्का लगता है और यह बुरा विचार है । इसके बजाय, डेवलपर्स को सफलता के गड्ढे की ओर धकेलें । JVM को क्रैश किए बिना अपने इंटरफ़ेस को सही ढंग से उपयोग करना आसान बनाएं ।

तरीकों के बीच प्रतिनिधिमंडल यहाँ ठीक है। हालांकि, निर्भरता को एक तरह से जाना चाहिए। मैं निर्देशन ग्राफ की तरह विधि प्रतिनिधिमंडल के बारे में सोचना पसंद करता हूं । प्रत्येक विधि ग्राफ पर एक नोड है। जब भी कोई विधि किसी अन्य विधि को कॉल करती है, तो कॉलिंग विधि से कॉल की गई विधि के लिए एक किनारा खींचें।

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


बहुत बढ़िया जवाब। मैं उत्सुक हूं कि हास्केल में ऐसा आम व्यवहार क्यों है। मुझे लगता है कि विभिन्न देव संस्कृतियों।
तवियन बार्न्स

मैं हास्केल में अनुभव नहीं कर रहा हूं और यह नहीं कह सकता कि यह कार्यात्मक प्रोग्रामिंग में अधिक प्रचलित है या क्यों नहीं।

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

1
अधिकांश कार्यात्मक प्रोग्रामिंग भाषाओं में टेल कॉल ऑप्टिमाइज़ेशन है। इस अनुकूलन के साथ, पूंछ पुनरावृत्ति स्टैक को नहीं उड़ाएगी, इस प्रकार ऐसी प्रथाएं समझ में आती हैं।
जेसन यियो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.