Diseño genérico de analizador de archivos en Java usando el patrón de Estrategia

14

Estoy trabajando en un producto en el que la responsabilidad de uno de los módulos es analizar los archivos XML y volcar el contenido requerido en una base de datos. A pesar de que el requisito actual es solo analizar archivos XML, quiero diseñar mi módulo de análisis de manera que pueda admitir cualquier tipo de archivos en el futuro. El motivo de este enfoque es que estamos creando este producto para un cliente específico, pero planeamos venderlo a otros clientes en un futuro próximo. Todos los sistemas en el ecosistema para el cliente actual producen y consumen archivos XML, pero este puede no ser el caso para otros clientes.

¿Qué he intentado hasta ahora? (El presente) Tengo en mente el siguiente diseño que se basa en el patrón de la Estrategia. Rápidamente escribí el código en eclipse para transmitir mi diseño, por lo que sería genial si se ignoraran otros aspectos, como la forma adecuada de manejar las excepciones, por ahora.

Analizador: La interfaz de la estrategia que expone un método de análisis.

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

* La razón para usar un parámetro genérico es permitir cualquier tipo de devolución, así como garantizar la seguridad del tipo en el momento de la compilación.

ProductDataXmlParser Una clase concreta para analizar un archivo product.xml que contiene información relacionada con el producto. (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();
    }
} 

donde : ProductDataTYPE y ProductDataDocument son clases POJO XMlBean generadas usando un xsd y el comando scomp.

El futuro

Si tengo un archivo product.txt para ser analizado en el futuro, puedo definir mi propio POJO llamado ProductData que contendrá el contenido requerido del archivo. Luego puedo crear una clase concreta llamada ProductDataFlatFileParser que implementa la interfaz del analizador y hacer que el método de análisis rellene el ProductData POJO para mí después de analizar el archivo.

¿Este diseño tiene sentido? ¿Hay defectos obvios en este diseño? Como el diseño se mantiene, estoy permitiendo que las clases concretas definan el algoritmo para analizar un archivo y dejo que la clase concreta decida dónde poblar los datos. El diseño parece depender más de los objetos del dominio que de los formatos de archivo. ¿Esto es malo? Cualquier aportación sobre cómo puedo mejorar mi diseño será muy apreciada.

    
pregunta CKing 18.02.2013 - 16:39

4 respuestas

7

Tengo un par de preocupaciones:

  1. Me aseguraría de que realmente necesite un diseño genérico antes de implementar uno. ¿Estás seguro de que necesitarás tipos de archivo distintos de XML? Si no, ¿por qué codificar para ellos? Si finalmente lo necesita, puede actualizar su código en ese momento. No tomará mucho más tiempo, probablemente tendrá otros requisitos que harán que el código se vea diferente a lo que está proponiendo actualmente, y probablemente nunca necesite escribirlo de todos modos. Como dicen, YAGNI (No lo vas a necesitar).
  2. Si realmente necesita un diseño genérico, y está bastante seguro de esto, entonces diría que Parser<T> es básicamente correcto. Veo dos problemas potenciales: (1) asume la entrada del archivo: ¿qué sucede si está intentando analizar una secuencia JSON que recuperó de una respuesta HTTP, por ejemplo? y (2) no necesariamente proporciona mucho valor excepto como parte de un marco genérico más grande en el que tiene muchos tipos diferentes de analizadores para muchos tipos diferentes de datos. Pero no estoy convencido de que necesite un marco genérico tan grande. En este momento solo tiene un caso de uso muy simple y concreto, por lo que puedo decir: analizar un archivo XML en una lista de ProductData s.
  3. Casi nunca es una buena idea tragar excepciones como lo está haciendo en ProductDataXmlParser . Lo convertiría en una especie de RuntimeException en su lugar.
respondido por el Eric Galluzzo 18.02.2013 - 15:51
1

Su diseño no es la mejor opción. Por su diseño, la única forma de utilizarlo:

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

No podemos ver demasiado beneficio del ejemplo anterior. No podemos hacer cosas como esta:

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

Puede considerar las siguientes dos opciones antes de buscar el genérico:

  • 1, la misma salida después del análisis

No importa de dónde sea la fuente de datos, los datos del producto tendrán el mismo formato antes de guardarlos en la base de datos. Es el contrato entre el cliente y su servicio de volcado. Así que asumo que tienes los mismos ProductData como resultado. Simplemente puede definir una interfaz:

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

Además, puede definir ProductData como interfaz si desea que sea más flexible.

Si no desea que el analizador se mezcle con los datos. Puedes dividirlo en dos interfaces:

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

Y tu analizador se verá así:

public class XMLParser implements Parser, Data {} 
public class TextParser implements Parser, Data {}
  • 2, salida diferente después del análisis

Si ProductData no es similar y desea reutilizar la interfaz del analizador. Puedes hacerlo de esta manera:

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();        
}
    
respondido por el Canhua Li 26.03.2016 - 19:44
-1

Yo también tengo el mismo requisito. Para un cliente necesito analizar el archivo XML, para otro archivo csv del cliente. Entonces, ¿siguió el procedimiento que mencionó o siguió algún enfoque nuevo? Por favor, hágame saber qué patrón ha utilizado.

    
respondido por el basha 26.02.2013 - 21:02
-2

En caso de que prefiera usar algo ya disponible, he creado una biblioteca java llamada JRecordBind que se basa en XMLSchema (respaldado por JAXB).

Nació para consumir / producir archivos de longitud fija y, dado que XMLSchema define su estructura, puede usarlo con JAXB simple para organizar / desmarcar todos los archivos XML

    
respondido por el Federico Fissore 19.02.2013 - 09:08

Lea otras preguntas en las etiquetas