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 Person
s. 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 Person
atualizar?
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 alterarDateOfBirth
e 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?
Person
instâ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á.