Imaginem uma classe Pessoa, com os atributos nome e idade. Para cada objeto da classe Pessoa eu gostaria de ter um histórico com todas as modificações, um atributo List historico. Essa classe PessoaItemHistorico poderia implementar a interface ItemHistorico, que obrigaria a implementação de getters e setters de atributos em comum como usuário que fez a modificação do objeto, data da modificação. Poderíamos também pensar na criação de uma outra interface, algo como Historiavel (eu não achei um nome melhor :(), que obrigari a classe a implementar um método getItensHistorico().
Vocês estão de acordo com este modelo? Existe algum tipo de padrão para situações desse tipo?
Fora essa questão, estou particularmente preocupado com o modelo físico do banco de dados, pois mantenho duas tabelas (imaginem “pessoa” e “pessoahistorico”). Se eu precisar mudar o tipo de dado da coluna “nome” de VARCHAR(40) para VARCHAR(100) tenho que lembrar de mudar nas duas tabelas, caso contrário terei problemas na inserção de registros com mais de 40 caracteres. Para eliminar esse problema, pensei em deixar ambos os campos com VARCHAR(255) e tratar o limite de caracteres via código (o tamanho atualmente só é validado na camada de Visão), mas isso não resolve todo o problema. Alguém tem alguma sugestão para isso?
[quote=bonfarj]Imaginem uma classe Pessoa, com os atributos nome e idade. Para cada objeto da classe Pessoa eu gostaria de ter um histórico com todas as modificações, um atributo List historico. Essa classe PessoaItemHistorico poderia implementar a interface ItemHistorico, que obrigaria a implementação de getters e setters de atributos em comum como usuário que fez a modificação do objeto, data da modificação. Poderíamos também pensar na criação de uma outra interface, algo como Historiavel (eu não achei um nome melhor :(), que obrigari a classe a implementar um método getItensHistorico().
Vocês estão de acordo com este modelo? Existe algum tipo de padrão para situações desse tipo?
[/quote]
Sim, existe. E é esse mesmo. Mas com um detalhes.
A classe Pessoa sempre representa o item tal como ele é hoje e HistoricoPessoa sempre representa a pessoa como ela era numa certa data. Logo, para obter HistoricoPessoa para uma certa data o padrão é assim:
Pessoa p = // encontra uma pessoa
Pessoa hp = p.historyAt(Date.valueOf(2007,1,1));
Historico h = (Historico) hp;
hp é o historico da pessoa , ou seja, são os dados de p mas no dia que não hoje. Portanto
HistoricoPessoa é tb uma pessoa. Historico tem uma data. O usuário que fez a alteração é um dado optional do historico.
Realmente esse problema existe. vc tem várias opções mas nenhuma é à prova de bala
Dimensionar o seu campo corretamente para que não seja necessário mudar depois.
Corrigir ambos na mão quando necessário
Usar uma mecanismo de metadados que extrapole os metadados da tabela de historico baseado nos metadados da tabela original + metadados necessários para historico. Esta opção pode aumentar muito a sua infraestrutura. Uma variação deste mecanismo seria usar uma tabela exatamente igual à original (sem os campos de histórico) e ter um mecanismo que sincronize os metadados da tabela original com essa. Os dados de historico seriam guardados numa tabela à parte com uma chave apontado o item da tabela de historico. Ao ler seria feito um join das duas.
Valeu, Ferryman, estou dando uma olhada! Achei pouca documentação sobre ele na Internet, achei estranho isso, parece que não é um design pattern muito usado.
[color=red]ATUALIZAÇÃO[/color]: Só agora vi o post do sergiotaborda, vou começar a ler agora, parece interessante.