Existem várias maneiras de lidar com o problema de controle de versão; você pode fazer isso tendo uma função de carregamento por versão, pode tentar automatizar o processo, descrevendo (via atributos geralmente) a transformação da estrutura do ativo ao longo do tempo, pode fazer verificações específicas da versão nas funções de carregamento / gravação, etc. .
Eu gosto da abordagem "descreva as alterações", mas acho que tentar fazê-lo por meio de atributos fica rapidamente difícil . Eu usaria funções em vez disso; implemente uma função que transforma dados na versão N
em dados na versão N + 1
para toda a sua versão apropriada. No carregamento, verifique a versão com a mais recente e, se não estiver, execute os dados através de todas as funções de versão apropriadas. Sempre salve a versão mais recente.
Isso funciona melhor se você fizer a transformação quando os dados ainda estiverem em um formato de valor-chave de tempo de execução. Isso significa que você provavelmente desejará implementar uma representação para seus dados que é uma abordagem de "bolsa de propriedades de tempo de execução", porque não é possível usar o formulário de valor-chave subjacente de JSON ou XML se você tiver seu próprio formato binário. Se você não fizer isso, também precisará manter as definições de classe antigas, o que fica feio. Ser capaz de ter seus ativos nesse formato ruim de propriedade também é tremendamente útil para o desenvolvimento de editores de jogos.
Durante o desenvolvimento, à medida que você repete os dados, ele naturalmente flui para a versão mais recente e, eventualmente, você pode excluir as funções antigas de controle de versão. Essa é mais ou menos a mesma abordagem de alto nível que usamos para versão de recursos artísticos (como os mapas) em Guild Wars 2.
Agora, tudo dito, acho útil apoiar a serialização de texto e binária para ativos. Durante o desenvolvimento, mantenha todos os seus dados em um formato legível por humanos com base em XML ou JSON. Isso pode aumentar muito sua capacidade de iteração, porque você não precisa criar ferramentas tão complexas para editar os dados. Você pode voltar a fazer ajustes rápidos simples à mão.
Segundo, supondo que você ainda queira um formato binário para distribuir o jogo (que pode melhorar o tamanho ou o tempo de IO do arquivo, por isso é um desejo válido), projete suas APIs de serialização e desserialização para lidar com o controle de versão. O controle de versão ainda é útil em um contexto de remessa, porque, em algum momento, você pode querer enviar atualizações ou correções de bugs. Existem alguns documentos que descrevem os recursos de versão da serialização .NET e da serialização do Boost que você pode achar interessante. Se você estiver indo para suportar texto e formatos binários, certifique-se de testá-los de vez em quando (ou testes de build automatizado para fazê-lo, melhor ainda).