Digamos que você tenha algum tipo de estrutura de dados, que persiste em algum tipo de banco de dados. Para simplificar, vamos chamar essa estrutura de dados Person. Agora você está encarregado de criar uma API CRUD, que permite que outros aplicativos criem, leiam, atualizem e excluam Persons. Para simplificar, vamos supor que essa API seja acessada através de algum tipo de serviço da web.
Para as partes C, R e D do CRUD, o design é simples. Usarei notação funcional do tipo C # - a implementação pode ser SOAP, REST / JSON ou outra coisa:
class Person {
string Name;
DateTime? DateOfBirth;
...
}
Identifier CreatePerson(Person);
Person GetPerson(Identifier);
void DeletePerson(Identifier);
E a atualização? A coisa natural a fazer seria
void UpdatePerson(Identifier, Person);
mas como você especificaria quais campos Personatualizar?
Soluções que eu poderia encontrar:
Você sempre pode exigir que uma Pessoa completa seja aprovada, ou seja, o cliente faria algo assim para atualizar a data de nascimento:
p = GetPerson(id); p.DateOfBirth = ...; UpdatePerson(id, p);No entanto, isso exigiria algum tipo de consistência transacional ou bloqueio entre o Get e o Update; caso contrário, você poderá substituir outras alterações feitas em paralelo por outro cliente. Isso tornaria a API muito mais complicada. Além disso, é propenso a erros, uma vez que o pseudocódigo a seguir (assumindo uma linguagem de cliente com suporte a JSON)
UpdatePerson(id, { "DateOfBirth": "2015-01-01" });- que parece correto - não apenas mudaria DateOfBirth, mas também redefiniria todos os outros campos para nulo.
Você pode ignorar todos os campos que são
null. No entanto, como você faria a diferença entre não alterarDateOfBirthe deliberadamente alterá-lo para nulo ?Mude a assinatura para
void UpdatePerson(Identifier, Person, ListOfFieldNamesToUpdate).Mude a assinatura para
void UpdatePerson(Identifier, ListOfFieldValuePairs).Use algum recurso do protocolo de transmissão: Por exemplo, você pode ignorar todos os campos não contidos na representação JSON da Pessoa. No entanto, isso geralmente requer a análise do JSON e não é possível usar os recursos internos da sua biblioteca (por exemplo, WCF).
Nenhuma das soluções parece realmente elegante para mim. Certamente, este é um problema comum, então qual é a solução de melhores práticas usada por todos?
Personinstâncias recém-criadas que ainda não são persistentes e, no caso de o identificador ser decidido como parte do mecanismo de persistência, deixe-o como nulo. Quanto à resposta, a JPA usa um número de versão; se você ler a versão 23, quando atualizar o item, se a versão no DB for 24, a gravação falhará.