जावा में रणनीति पैटर्न का उपयोग करके सामान्य फ़ाइल पार्सर डिज़ाइन


14

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

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

पार्सर: वह रणनीति इंटरफ़ेस जो एक पार्स विधि को उजागर करता है।

 public interface Parser<T> {
        public T parse(String inputFile);
    }

* जेनेरिक पैरामीटर का उपयोग करने का कारण किसी भी वापसी प्रकार के साथ-साथ संकलन समय पर सुरक्षा सुनिश्चित करना है।

ProductDataXmlParser एक product.xml फ़ाइल को पार्स करने के लिए एक ठोस वर्ग जिसमें उत्पाद से संबंधित जानकारी होती है। (XMLBeans का उपयोग करके)

public class ProductDataXmlParser implements Parser<ProductDataTYPE> {

    public ProductDataTYPE parse(String inputFile) {
        ProductDataTYPE productDataDoc = null;
            File inputXMLFile = new File(inputFile);

        try {
            productDataDoc = ProductDataDocument.Factory.parse(inputXMLFile);
        } catch(XmlException e) {
            System.out.println("XmlException while parsing file : "+inputXMLFile);
        } catch(IOException e) { 
                 System.out.println("IOException while parsing file : "+inputXMLFile);
        }
        return productDataDoc.getProductData();
    }
} 

कहाँ : ProductDataTYPE और ProductDataDocument एक xsd और scomp कमांड का उपयोग करके उत्पन्न की जाने वाली XMlBean POJO कक्षाएं हैं।

भविष्य

अगर मेरे पास भविष्य में पार्स की जाने वाली एक उत्पाद.टैक्स फ़ाइल है, तो मैं अपने खुद के POJO को परिभाषित कर सकता हूं जिसे ProductData कहा जाता है जो फ़ाइल की आवश्यक सामग्री को रखेगा। मैं तब ProductDataFlatFileParser नामक एक ठोस वर्ग बना सकता हूँ जो पार्सर इंटरफ़ेस को लागू करता है और फ़ाइल को पार्स करने के बाद मेरे लिए ProductData POJO को पार्स करने की विधि है।

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


क्या सॉफ्टवेयर को फोन करने वाले को यह पता नहीं होने देना चाहिए कि फाइल फॉर्मेट का समर्थन क्या है? आपका सॉफ्टवेयर कैसे जानता है कि किस पार्सर को आह्वान करना है?
टोमडेमुइट

आप अपने डिज़ाइन पर प्रतिक्रिया की तलाश कर रहे हैं , न कि आपके वास्तविक कार्यान्वयन की , इसलिए यह प्रोग्रामर्स को माइग्रेट किया जाएगा जहां यह विषय पर है।
कोडस्पार्कल

@tomdemuyt फैक्ट्री पैटर्न सोचो ;)
CKing

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

2
कृपया या तो क्रॉसपोस्ट न करें। आप एक गड़बड़ कर रहे हैं जिसे हमें साफ करना है।
बंद Ripped

जवाबों:


7

मुझे कुछ चिंताएँ हैं:

  1. मैं यह सुनिश्चित करूंगा कि किसी को लागू करने से पहले आपको वास्तव में एक सामान्य डिजाइन की आवश्यकता होगी। क्या आप वाकई XML से भिन्न फ़ाइल प्रकारों की आवश्यकता वाले हैं? यदि नहीं, तो उनके लिए कोड क्यों? यदि आपको अंततः इसकी आवश्यकता है, तो आप उस बिंदु पर अपने कोड को वापस कर सकते हैं। यह अधिक समय नहीं लेगा, आपके पास संभवतः अन्य आवश्यकताएं होंगी जो कोड को वर्तमान में आप जो प्रस्ताव दे रहे हैं उससे अलग दिखेंगे, और आपको इसे कभी भी लिखने की आवश्यकता नहीं होगी। जैसा कि वे कहते हैं, YAGNI (यू एन गॉन नीड इट)।
  2. यदि आपको वास्तव में एक सामान्य डिजाइन की आवश्यकता है, और आप इसके बारे में निश्चित हैं, तो मैं कहूंगा कि Parser<T>मूल रूप से ध्वनि है। मुझे दो संभावित समस्याएं दिखाई देती हैं: (1) यह फ़ाइल इनपुट को मानता है - क्या होगा यदि आप एक JSON स्ट्रीम को पार्स करने की कोशिश कर रहे हैं जिसे आपने HTTP प्रतिक्रिया से प्राप्त किया है, उदाहरण के लिए? और (2) यह आवश्यक रूप से कुछ बड़े सामान्य ढांचे के हिस्से को छोड़कर बहुत अधिक मूल्य प्रदान नहीं करता है जहां आपके पास बहुत से विभिन्न प्रकार के डेटा के लिए बहुत सारे प्रकार के पार्सर हैं। लेकिन मुझे यकीन नहीं है कि आपको किसी ऐसे बड़े जेनेरिक ढांचे की जरूरत है। आपके पास अभी एक बहुत ही सरल, ठोस उपयोग का मामला है, जहां तक ​​मैं बता सकता हूं: XML फ़ाइल को सूची में पार्स करें ProductData
  3. अपवादों को निगलने के लिए लगभग एक अच्छा विचार नहीं है जैसा कि आप कर रहे हैं ProductDataXmlParser। मैं इसे RuntimeExceptionबदले के कुछ प्रकार में परिवर्तित करूंगा ।

1
हम एक ऐसे उत्पाद का निर्माण कर रहे हैं जो बहुत सारी बाहरी प्रणालियों के साथ संवाद करेगा इसलिए मुझे लगता है कि किसी भी तरह की फ़ाइल या इनपुट प्रारूप के लिए यह एक अच्छा विचार होगा। JSON स्ट्रीम के बारे में उत्कृष्ट बिंदु। यही कारण है कि मेरे पास पार्सर इंटरफ़ेस में मेरा पार्स तरीका एक फ़ाइल पैरामीटर के बजाय एक स्ट्रिंग पैरामीटर था। मेरे ProductDataXmlParser में मेरी एक छोटी सी गलती थी जिसे मैंने ठीक कर दिया है (XmlBean parser में फाइल पास करने की आवश्यकता है)। आप अपवादों को निगलने के बारे में भी सही हैं। मैंने एक उदाहरण के माध्यम से
स्टैकओवरफ़्लो

अच्छा ठीक है। मुझे लगता है कि मैं पार्सर पैरामीटर को एक स्ट्रिंग के बजाय एक इनपुटस्ट्रीम बनाऊंगा, यही मैं कह रहा हूं। :) और अपवाद के बारे में सुनने के लिए अच्छा है - मुझे यकीन नहीं था कि अगर आपके वास्तविक कोड या 'StackOverflow' के लिए सिर्फ नमूना कोड से काट दिया गया था।

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

मैं एक विचार दे दूंगा कि तुम क्या कह रहे हो। मैं बताना चाहूंगा कि 4 अलग-अलग xml फाइलें हैं जिनमें पार्स करने के लिए 4 अलग-अलग प्रकार के डेटा हैं। उत्पाद डेटा हमारे सिस्टम / उत्पाद द्वारा खपत किए जाने वाले डेटा का केवल एक प्रकार है।
Cking

मेरे पास आपके लिए एक और सवाल है। मैं एक संदर्भ का उपयोग नहीं करने जा रहा हूं जो कि रणनीति पैटर्न का एक हिस्सा है। क्या यह ठीक होगा? मैं सामान्य पैरामीटर से छुटकारा पा रहा हूं और पार्सर इंटरफ़ेस में पार्स विधि में ऑब्जेक्ट वापस कर रहा हूं। यह उन वर्गों से बचने के लिए है जो पार्सर का उपयोग एक प्रकार के पैरामीटर के साथ घोषित करने के लिए करते हैं।
CKing

1

आपका डिजाइन एक सबसे अच्छा विकल्प नहीं है। आपके डिज़ाइन द्वारा, इसका उपयोग करने का एकमात्र तरीका:

ProductDataXMLTYPE parser = new ProductDataXmlParser<ProductDataXMLTYPE>().parse(input); 
ProductDataTextTYPE parser = new ProductDataTextParser<ProductDataTextTYPE >().parse(input);

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

Parser parser = getParser(string parserName);
parser.parse();

आप जेनेरिक की तलाश करने से पहले निम्नलिखित दो विकल्पों पर विचार कर सकते हैं:

  • 1, पार्स के बाद एक ही उत्पादन

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

public interface Parser {
    public ProductData parse(String inputFile);
}

इसके अलावा आप अगर आप इसे और अधिक लचीला चाहते हैं तो ProductData को इंटरफ़ेस के रूप में परिभाषित करें।

यदि आप नहीं चाहते कि पार्सर डेटा के साथ मिलाया जाए। आप इसे दो इंटरफ़ेस में विभाजित कर सकते हैं:

public interface Parser {
     public void parse(String inputFile);
}
public interface Data {
    public ProductData getData();
}

और आपका पार्सर इस तरह दिखेगा:

public class XMLParser implements Parser, Data {} 
public class TextParser implements Parser, Data {}
  • 2, पार्स के बाद अलग उत्पादन

यदि ProductData समान नहीं है और आप पार्सर इंटरफ़ेस का पुन: उपयोग करना चाहते हैं। आप इसे इस तरह से कर सकते हैं:

public interface Parser {
   public void parse(String inputFile);
}

class XMLParse implements {
      @Override
      public void parse(String inputFile);

      ProductDataXML getProductData();        
}

class TextParse implements {
      @Override
      public void parse(String inputFile);

      ProductDataText getProductData();        
}

-2

यदि आप पहले से उपलब्ध कुछ का उपयोग करना पसंद करेंगे, तो मैंने JRecordBind नामक एक जावा लाइब्रेरी बनाई है जो XMLSchema (JAXB द्वारा समर्थित) पर आधारित है।

यह निश्चित लंबाई की फ़ाइलों का उपभोग / उत्पादन करने के लिए पैदा हुआ था, और, चूंकि XMLSchema उनकी संरचना को परिभाषित करता है, आप इसे सादे JAXB के साथ मार्शेल / अनमरशाल XML फ़ाइलों में उपयोग कर सकते हैं


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