Qual é um bom design para permitir a compatibilidade com versões anteriores de um tipo de arquivo entre diferentes versões de software?
Por exemplo, como a Microsoft obtém o Word 2007, 2010 e 2013 etc ... para todos os arquivos docx abertos, mas edições diferentes podem salvar mais / menos dados e salvá-los de maneiras ligeiramente diferentes, tudo para o mesmo tipo de arquivo e um o arquivo salvo em uma versão pode ser aberto em outra, mas certos elementos do arquivo podem não estar disponíveis em versões mais antigas?
Quero dizer, a maneira realmente óbvia de fazer isso é ter algo como
private string openfile(string filename)
{
File.Open(filename)
... some logic that gets a header from the file that will never change
switch (fileversion)
case 2007:
.....
case 2010
.....
case 2013
.....
}
mas isso parece incrivelmente monolítico, não muito extensível e provavelmente leva a muitos códigos copiados / colados.
Então, eu estava pensando em usar uma interface de base para todas as versões que definem as estruturas imutáveis, como o cabeçalho, que precisam estar presentes no arquivo e os métodos que precisam estar disponíveis para serialização / desserialização e, em seguida, herança múltipla para que cada A classe da nova versão que implementa a interface herda a versão antiga e substitui apenas as coisas que foram alteradas, já que o arquivo será o mesmo, na maior parte.
Não estou realmente preocupado com a estrutura do arquivo, pois já está decidido que usaremos XML, e o esquema inicial já está, em geral, decidido. No entanto, sem dúvida, haverá alterações no futuro, e eu só quero poder projetar o código de uma maneira que facilite a acomodação dessas alterações.
fonte
Respostas:
Você pode dar uma olhada no formato de arquivo PNG e como ele lida com a compatibilidade de versão. Cada bloco possui um ID que descreve o tipo de bloco e possui alguns sinalizadores que informam ao software o que fazer se não conseguir entender esse ID. Por exemplo "você não pode ler o arquivo se não entender este bloco" ou "você pode ler o arquivo, mas não pode modificá-lo" ou "você pode modificar o arquivo, mas precisa excluir este bloco". Para compatibilidade com versões anteriores, seu software só precisa lidar com a situação quando nenhum dado esperado estiver presente.
fonte
Uma maneira de fazer isso pode ser usando uma classe base e uma interface com as funções básicas para o tratamento de arquivos. Em seguida, use classes para cada versão que se estende da classe base para lidar com todos os casos específicos da versão. As funções que podem mudar podem ser virtuais na classe de resumo base, se houver apenas implementações específicas da versão. Quando você precisar de uma classe para manipular o arquivo, use uma fábrica que obtenha a implementação específica da versão da interface de manipulação de arquivos.
fonte
Eu fiz isso com XML e funciona bem:
Simplesmente permita que qualquer elemento do seu documento tenha atributos e subelementos (e quando a ordem não for importante - em qualquer ordem). A partir da primeira versão do programa - ao ler o documento, ignore os atributos e subelementos que você não conhece na versão atual.
No futuro, quando você estiver adicionando um novo recurso à nova versão do programa, adicione atributo ou subelemento. As versões mais antigas irão ignorá-lo. A nova versão deve verificar a pressão do atributo ou subelemento e lidar com isso.
Por exemplo, você tem alguns itens com textos:
E na versão mais recente, você gostaria de adicionar cor ao item para adicionar o atributo
color
:A versão mais antiga simplesmente ignorará o
color
atributo ao abrir o documento. Novas versões verificam a pressão docolor
atributo e, se não existe, atribuem a cor padrão.Com esta solução simples, você terá compatibilidade com versões anteriores e posteriores.
fonte