Se possível, a introdução de um número de versão em cada estrutura é uma abordagem, que é particularmente popular com APIs REST e formatos de arquivo (texto simples e binário). Seu aplicativo, então, tem a capacidade de atualizar cada versão para a próxima. Isso significa que você só precisa se preocupar com um caminho de atualização, e pode apenas encadear atualizações conforme necessário. Se desejar, é possível adicionar outros caminhos de atualização para acelerar e até mesmo fazer downgrade de caminhos (geralmente são visíveis em programas em que várias versões são mantidas ao mesmo tempo e geralmente há um custo que impede que muitos clientes façam upgrade imediatamente).
Então, por exemplo, talvez você tenha uma Employee
struct. Talvez a versão um seja realmente simples:
{
'_version': '1.0'
'first_name': 'Amelia',
'last_name': 'Bedelia',
'employee_id': 123,
'salary': 65000
}
Mas depois, suponha que realmente queremos combinar esse campo de nome. Vamos apenas fazer essa mudança porque, presumivelmente, há uma boa razão comercial para isso! Temos uma nova versão para nossa estrutura:
{
'_version': '1.1'
'name': 'Amelia Bedelia',
'employee_id': 123,
'salary': 65000
}
Agora, nós poderíamos ter apenas nossa ramificação da base de código no número da versão, mas é muito mais à prova do futuro e geralmente mais limpa para simplesmente atualizar a estrutura antiga para algo compatível com a nova. Isso pode envolver o preenchimento de padrões razoáveis, ler informações adicionais de outros lugares para preencher espaços em branco, solicitar aos usuários essas informações ou o que for. A ideia, no entanto, é garantir que sua base de código só precise lidar com a versão mais recente da estrutura.
Portanto, teríamos alguma função de atualização que tenha algum ramo como:
if employee['_version'] == '1.0':
# Let's just make an assumption about names and combine it blindly
employee = {
'_version': '1.1',
'name': employee['first_name'] + ' ' + employee['last_name'],
'employee_id': employee['employee_id'],
'salary': employee['salary']
}
# And so on for other version upgrades, returning the final object
# at the end.
E então continuaríamos fazendo isso até que tenhamos a versão atual (que poderia então ser convertida em um tipo mais strong). Esse padrão também funciona bem para atualizações de banco de dados (é como o manuseio recomendado do Android para seus bancos de dados SQLite funciona).
Agora, esta resposta tem sido de alto nível até agora. Mas não é exclusivo para onde a estrutura de dados pode ser representada como um dicionário genérico (embora seja certamente uma estrutura de dados versátil e adaptável para troca de informações entre os limites do sistema). Se os dados puderem ser armazenados em um formato binário bruto e sempre tivermos a versão em uma determinada posição, poderemos escolher facilmente qual estrutura de baixo nível será usada para interpretar os dados (e depois aplicar a atualização a partir deles). Nesse caso, ainda precisaríamos armazenar essas estruturas em algum lugar (mas o valor vem de não ter muitos caminhos de código para essas diferentes versões de estruturas).