Estou trabalhando em um produto no qual a responsabilidade de um dos módulos é analisar arquivos XML e despejar o conteúdo necessário em um banco de dados. Mesmo que o requisito atual seja apenas analisar arquivos XML, desejo projetar meu módulo de análise de forma que possa suportar qualquer tipo de arquivo no futuro. O motivo dessa abordagem é que estamos construindo este produto para um cliente específico, mas planejamos vendê-lo para outros clientes em um futuro próximo. Todos os sistemas no ecossistema para o cliente atual produzem e consomem arquivos XML, mas isso pode não ser o caso para outros clientes.
O que eu tentei até agora? (O presente) Tenho em mente o seguinte design, baseado no padrão de estratégia. Eu rapidamente escrevi o código no eclipse para transmitir meu design, então seria ótimo se outros aspectos, como a maneira correta de lidar com exceções, fossem ignorados por enquanto.
Analisador: a interface da estratégia que expõe um método de análise.
public interface Parser<T> {
public T parse(String inputFile);
}
* O motivo do uso de um parâmetro genérico é permitir qualquer tipo de retorno e garantir a segurança do tipo no momento da compilação.
ProductDataXmlParser Uma classe concreta para analisar um arquivo product.xml que contém informações relacionadas ao produto. (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();
}
}
em que : ProductDataTYPE e ProductDataDocument são classes XMlBean POJO geradas usando um xsd e o comando scomp.
O futuro
Se eu tiver um arquivo product.txt a ser analisado no futuro, posso definir meu próprio POJO chamado ProductData que conterá o conteúdo necessário do arquivo. Em seguida, posso criar uma classe concreta chamada ProductDataFlatFileParser que implementa a interface Parser e fazer com que o método de análise preencha o POJO ProductData para mim depois de analisar o arquivo.
Esse design faz sentido? Existem falhas óbvias nesse design? Como está o design, estou permitindo que as classes concretas definam o algoritmo para analisar um arquivo e deixe a classe concreta decidir onde preencher os dados. O design parece ser mais dependente dos objetos do domínio do que dos formatos de arquivo. Isso é ruim? Quaisquer contribuições sobre como melhorar meu design serão muito apreciadas.
Respostas:
Tenho algumas preocupações:
Parser<T>
é basicamente bom. Eu vejo dois problemas em potencial: (1) ele assume a entrada do arquivo - e se você estiver tentando analisar um fluxo JSON recuperado de uma resposta HTTP, por exemplo? e (2) não necessariamente fornece muito valor, exceto como parte de uma estrutura genérica maior, na qual você tem muitos tipos diferentes de analisadores para muitos tipos diferentes de dados. Mas não estou convencido de que você precise de uma estrutura genérica tão grande. Você apenas tem um caso de uso concreto muito simples agora, tanto quanto posso dizer: analise um arquivo XML em uma lista deProductData
s.ProductDataXmlParser
. Eu o converteria para algum tipo deRuntimeException
alternativa.fonte
Seu design não é a melhor opção. Pelo seu design, a única maneira de usá-lo:
Não podemos ver muitos benefícios do exemplo acima. Não podemos fazer coisas assim:
Você pode considerar as duas opções a seguir antes de procurar o genérico:
Independentemente da origem da fonte de dados, os dados do produto terão o mesmo formato antes de salvá-los no banco de dados. É o contrato entre o cliente e seu serviço de despejo. Então, suponho que você tenha o mesmo ProductData da saída. Você pode simplesmente definir uma interface:
Além disso, você define ProductData como interface, se quiser mais flexível.
Se você não deseja que o Analisador seja misturado com os dados. Você pode dividi-lo em duas interfaces:
E seu analisador ficará assim:
Se o ProductData não for semelhante e você desejar reutilizar a interface do Parser. Você pode fazer assim:
fonte
Apenas no caso de você preferir usar algo já disponível, eu fiz uma biblioteca java chamado JRecordBind que é baseada em XMLSchema (apoiado por JAXB).
Nasceu para consumir / produzir arquivos de tamanho fixo e, como o XMLSchema define sua estrutura, você pode usá-lo com JAXB simples para ordenar / desmarcar arquivos XML
fonte