Progettazione di parser di file generici in Java utilizzando il modello di strategia

14

Sto lavorando su un prodotto in cui la responsabilità di uno dei moduli è quella di analizzare i file XML e scaricare il contenuto richiesto in un database. Anche se l'attuale requisito è solo quello di analizzare i file XML, voglio progettare il mio modulo di analisi in modo tale che possa supportare qualsiasi tipo di file in futuro. La ragione di questo approccio è che stiamo costruendo questo prodotto per un cliente specifico ma intendiamo venderlo ad altri clienti nel prossimo futuro. Tutti i sistemi nell'ecosistema per il client corrente producono e consumano file XML, ma questo potrebbe non essere il caso per altri client.

Che cosa ho provato finora? (Il presente) Ho in mente il seguente disegno che si basa sul modello di strategia. Ho rapidamente annotato il codice in eclissi per trasmettere il mio progetto in modo che sarebbe bello se altri aspetti come il modo corretto di gestire le eccezioni sono ignorati per ora.

Parser: l'interfaccia della strategia che espone un metodo di analisi.

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

* Il motivo dell'utilizzo di un parametro generico è quello di consentire qualsiasi tipo di ritorno e garantire la sicurezza del tipo in fase di compilazione.

ProductDataXmlParser Una classe concreta per l'analisi di un file product.xml che contiene informazioni correlate al prodotto. (usando 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();
    }
} 

dove : ProductDataTYPE e ProductDataDocument sono classi POJO XMlBean generate utilizzando un comando xsd e il comando scomp.

Il futuro

Se ho un file product.txt da analizzare in futuro, posso definire il mio POJO chiamato ProductData che conserverà i contenuti richiesti del file. Posso quindi creare una classe concreta chiamata ProductDataFlatFileParser che implementa l'interfaccia Parser e avere il metodo di analisi per compilare il POJO ProductData per me dopo aver analizzato il file.

Questo progetto ha senso? Ci sono evidenti difetti in questo design? Mentre il design sta in piedi, sto permettendo alle classi concrete di definire l'algoritmo per analizzare un file e lasciare che la classe concreta decida dove popolare i dati. Il design sembra essere più dipendente dagli oggetti del dominio piuttosto che dai formati di file. è una cosa negativa? Ogni input su come posso migliorare il mio design sarà molto apprezzato.

    
posta CKing 18.02.2013 - 16:39
fonte

4 risposte

7

Ho un paio di dubbi:

  1. Mi assicurerei che tu abbia effettivamente bisogno di un design generico prima di implementarne uno. Sei sicuro di aver bisogno di tipi di file diversi da XML? Se no, perché programmare per loro? Se alla fine ne hai bisogno, puoi adattare il tuo codice a quel punto. Non ci vorrà molto più tempo, probabilmente avrai altri requisiti che renderanno il codice diverso da quello che stai proponendo e probabilmente non avresti mai bisogno di scriverlo comunque. Come si suol dire, YAGNI (non ne hai bisogno).
  2. Se hai effettivamente bisogno di un design generico e ne sei abbastanza sicuro, allora direi che Parser<T> è fondamentalmente audio. Vedo due potenziali problemi: (1) presuppone l'input dei file - cosa succede se si sta tentando di analizzare un flusso JSON recuperato da una risposta HTTP, ad esempio? e (2) non fornisce necessariamente molto valore se non come parte di un quadro generico più ampio in cui si hanno molti diversi tipi di parser per molti tipi diversi di dati. Ma non sono convinto che tu abbia bisogno di un quadro generico così ampio. Hai solo un caso d'uso concreto molto semplice in questo momento, per quanto posso dire: analizzare un file XML in un elenco di ProductData s.
  3. Non è quasi mai una buona idea ingoiare le eccezioni come si fa in ProductDataXmlParser . Lo convertirò in una sorta di RuntimeException invece.
risposta data 18.02.2013 - 15:51
fonte
1

Il tuo design non è l'opzione migliore. Dal tuo design, l'unico modo per usarlo:

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

Non possiamo vedere troppi benefici dall'esempio sopra. Non possiamo fare cose del genere:

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

Puoi prendere in considerazione le seguenti due opzioni prima di cercare il generico:

  • 1, stesso risultato dopo analisi

Indipendentemente da dove proviene l'origine dati, i dati del prodotto avranno lo stesso formato prima di salvarlo nel database. È il contratto tra il cliente e il tuo servizio di dumping. Quindi presumo che tu abbia lo stesso ProductData come output. Puoi semplicemente definire un'interfaccia:

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

Inoltre, si definisce ProductData come interfaccia se lo si desidera più flessibile.

Se non si desidera che il parser venga mixato con i dati. Puoi dividerlo su due interfacce:

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

E il tuo parser sarà simile a questo:

public class XMLParser implements Parser, Data {} 
public class TextParser implements Parser, Data {}
  • 2, output diverso dopo analisi

Se ProductData non è simile e si desidera riutilizzare l'interfaccia Parser. Puoi farlo in questo modo:

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();        
}
    
risposta data 26.03.2016 - 19:44
fonte
-1

Anch'io ho lo stesso requisito. Per un cliente ho bisogno di analizzare il file XML, per un altro file csv del client. Quindi, hai seguito la procedura che hai menzionato o hai seguito un nuovo approccio. Per favore fatemi sapere quale schema avete usato.

    
risposta data 26.02.2013 - 21:02
fonte
-2

Nel caso in cui preferisci usare qualcosa già disponibile, ho creato una libreria java chiamata JRecordBind basata su XMLSchema (supportato di JAXB).

È nato per consumare / produrre file a lunghezza fissa e, dal momento che XMLSchema definisce la loro struttura, è possibile utilizzarlo con un semplice JAXB nei file XML marshall / unmarshall

    
risposta data 19.02.2013 - 09:08
fonte

Leggi altre domande sui tag