2009-04-27 12 views
8

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

public interface MyCrazyAnalyzer { 
    public void setOptions(AnalyzerOptions options); 
    public void setText(String text); 
    public void initialize(); 
    public int getOccurances(String query); 
} 

और उम्मीद उपयोग इस तरह है:

MyCrazyAnalyzer crazy = AnalyzerFactory.getAnalyzer(); 
crazy.setOptions(true); 
crazy.initialize(); 
Map<String, Integer> results = new HashMap<String, Integer>(); 
for(String item : items) { 
    crazy.setText(item); 
    results.put(item, crazy.getOccurances); 
} 

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

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

मेरे प्रश्न हैं:

  1. हर कोई इस बात से सहमत है कि यह एक खराब तरीके से तैयार इंटरफ़ेस है?
  2. क्या यह एक वर्णित विरोधी पैटर्न है?
  3. क्या इस प्रकार की शुरुआत कभी इंटरफ़ेस में होती है?
  4. क्या यह केवल मेरे लिए गलत लगता है क्योंकि मुझे कार्यात्मक शैली और अपरिवर्तनीयता के लिए प्राथमिकता है?

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

+0

ईमानदारी से कहूं तो यह "पैटर्न" ADO.NET में DataReaders को मुझे याद दिलाता है। इसका मतलब यह नहीं है कि यह एक अच्छा विचार है, लेकिन इसका उपयोग गंभीर एपीआई में भी किया जाता है। –

+0

अच्छा विरोधी पैटर्न। अगर वस्तुओं को इस तरह शुरू किया जाना था तो हम इंटरफेस में कन्स्ट्रक्टर निर्दिष्ट करने में सक्षम होंगे। मुझे 'गुप्त हैंडशेक' शब्द भी पसंद है। – CurtainDog

+0

कम से कम यह स्पष्ट रूप से खराब है, java.util.MessageFormat के विपरीत जो एकल विधि कॉल के दौरान अस्थायी आंतरिक स्थिति का उपयोग करता है। –

उत्तर

17

हाँ, यह एक विरोधी पैटर्न है: Sequential coupling

मैं Options में प्रतिक्रिया करता हूं - कारखाने में पास किया गया, और Results, analyseText() विधि से लौटा।

+13

बढ़िया, अब मैं कम विनम्र "भ्रमित कचरा हटाने" के बजाय अपने चेकइन संदेशों में "क्रमिक युग्मन हटाने" डाल सकता हूं। –

3
  1. मुझे उम्मीद है कि विश्लेषक कारखाना आवश्यक पैराम पास कर देगा और निर्माण स्वयं ही करेगा; अन्यथा, यह वास्तव में क्या कर रहा है?
  2. सुनिश्चित नहीं हैं कि अगर यह एक नाम है, लेकिन ऐसा लगता है जैसे कि यह :) चाहिए
  3. हाँ, कभी कभी यह सुविधाजनक है (और अमूर्त का सही स्तर) अपने इंटरफेस में setters हैं और उन्हें फोन करने के लिए कक्षाओं अपेक्षा करनी चाहिए। मैं सुझाव दूंगा कि ऐसा करने के लिए उस तथ्य के व्यापक दस्तावेज़ीकरण की आवश्यकता है।
  4. वास्तव में नहीं, नहीं। अपरिवर्तनीयता के लिए प्राथमिकता निश्चित रूप से एक अच्छी बात है, और सेटटर/बीन आधारित डिजाइन कभी-कभी "सही" विकल्प भी हो सकता है, लेकिन आपका दिया गया उदाहरण इसे बहुत दूर ले रहा है।
+0

+1 क्योंकि मैं सोच रहा था कि फैक्ट्री क्या कर रही थी ... ऐसा लगता है कि यह सिर्फ वैश्विक संसाधन के रूप में उपयोग किया जा रहा है, दूसरा नंबर नहीं। – CurtainDog

3

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

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

Joshua Bloch वास्तव में एपीआई डिज़ाइन पर एक उत्कृष्ट presentation (36m16s और 40m30s) है और वह इसे खराब डिजाइन किए गए API की विशेषताओं में से एक के रूप में संबोधित करता है।

0

मैं कुछ भी बुरा यहाँ में नहीं देख सकता। setText() मंच तैयार करता है; इसके बाद, आपके पास getOccurances() पर एक या अधिक कॉल हैं। चूंकि setText() इतना महंगा है, इसलिए मैं ऐसा करने के किसी अन्य तरीके से नहीं सोच सकता।

getOccurances(text, query) एक जबरदस्त प्रदर्शन कीमत पर "गुप्त हाथ मिलाना" ठीक होगा। आप getOccurances() में कैश पाठ की कोशिश कर सकते हैं और केवल अपने आंतरिक कैश अद्यतन पाठ परिवर्तन लेकिन यह है कि अधिक से अधिक कुछ OO सिद्धांत का बलिदान तरह देखने के लिए शुरू होता है जब। यदि कोई नियम समझ में नहीं आता है, तो इसे लागू न करें। सॉफ्टवेयर डेवलपर्स के पास एक कारण के लिए एक मस्तिष्क है।

+0

डगलस के सुझाव के अनुसार, इस तरह के कोड को किसी ऐसे वस्तु में दोबारा सुधारना संभव है जो परिणाम वस्तु लौटाता हो। –

0

एक संभव समाधान - Fluent chaning का उपयोग करें। इससे एक वर्ग से युक्त विधियों से बचा जाता है जिसे एक निश्चित क्रम में बुलाया जाना चाहिए। यह बिल्डर पैटर्न की तरह बहुत कुछ है जो सुनिश्चित करता है कि आप उन वस्तुओं को न पढ़ें जो अभी भी आबादी के बीच में हैं।

संबंधित मुद्दे