Estoy trabajando en un producto en el que la responsabilidad de uno de los módulos es analizar archivos XML y volcar el contenido requerido en una base de datos. Aunque 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. La razón de este enfoque es que estamos construyendo este producto para un cliente específico, pero planeamos venderlo a otros clientes en el futuro cercano. 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 probado hasta ahora? (El presente) Tengo en mente el siguiente diseño que se basa en el patrón de Estrategia. Rápidamente he escrito el código en eclipse para transmitir mi diseño, por lo que sería genial si otros aspectos, como la forma adecuada de manejar las excepciones, se ignoren por ahora.
Analizador: la interfaz de 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 retorno, así como garantizar la seguridad del tipo en tiempo de 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 analizar 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 Parser y hacer que el método de análisis llene el POJO ProductData por mí después de analizar el archivo.
¿Tiene sentido este diseño? ¿Hay defectos obvios en este diseño? Tal como está el diseño, estoy permitiendo que las clases concretas definan el algoritmo para analizar un archivo y que la clase concreta decida dónde poblar los datos. El diseño parece depender más de los objetos de dominio que de los formatos de archivo. ¿Esto es malo? Cualquier aportación sobre cómo puedo mejorar mi diseño será muy apreciada.
Respuestas:
Tengo un par de preocupaciones:
Parser<T>
es básicamente correcto. Veo dos problemas potenciales: (1) supone 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. Solo tiene un caso de uso muy simple y concreto en este momento, por lo que puedo decir: analizar un archivo XML en una lista deProductData
s.ProductDataXmlParser
. Lo convertiría en algún tipo deRuntimeException
lugar.fuente
Su diseño no es la mejor opción. Por su diseño, la única forma de usarlo:
No podemos ver muchos beneficios del ejemplo anterior. No podemos hacer cosas como esta:
Puede considerar las siguientes dos opciones antes de buscar el genérico:
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 supongo que tiene los mismos ProductData que la salida. Simplemente puede definir una interfaz:
Además, define ProductData como interfaz si desea que sea más flexible.
Si no desea que el analizador se mezcle con los datos. Puede dividirlo en dos interfaces:
Y su analizador se verá así:
Si ProductData no es similar y desea reutilizar la interfaz del analizador. Puedes hacerlo de esta manera:
fuente
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 marshall / unmarshall archivos XML
fuente