Por que o Protobuf 3 tornou todos os campos das mensagens opcionais?

15

A sintaxe 3 do protobuf tornou todos os campos opcionais, descartando as palavras-chave requirede a optionalsintaxe proto2 anterior. Lendo alguns comentários dos desenvolvedores , parece que foi feito para melhorar a compatibilidade binária para frente / trás.

Mas, para mim, isso poderia ser aplicado apenas com a versão dos nomes dos pacotes, digamos com.example.messages.v1e, em seguida, permitindo que os clientes implementem desserializadores que eles entendem. Ao mesmo tempo, remove alguns contratos declarados como um tipo que são úteis do ponto de vista da engenharia de software. Por exemplo, se eu tiver

message Location {
   double latitude = 1;
   double longitude = 2;
}

No proto3, é possível criar um meio respaldo, mas perfeitamente válido Location, não fornecendo um dos campos obrigatórios.

Isso não é uma grande desvantagem ao criar um formato de serialização baseado em esquema para a troca de dados entre clientes? Não é pior mover código de validação extra para cada cliente, verificando se todos os campos obrigatórios têm valores válidos?

tonicebrian
fonte
leanpub.com/esversioning
VoiceOfUnreason

Respostas:

13

O proto3 faz várias alterações destinadas (como eu o entendo) a torná-lo muito mais utilizável em cenários de plataforma cruzada. O rastreamento explícito de "atribuído" vs "não atribuído, mas relatando o valor padrão" pode ser muito difícil de implementar em algumas plataformas de destino e também pode ser confuso de usar. Como tal, o proto3 adota uma abordagem muito mais simples:

  • o valor padrão implícito é o valor zero natural (números / enumerações), false (booleanos) ou a string vazia (strings)
  • somente o padrão implícito é permitido; nenhum outro valor padrão é permitido
  • se um campo tiver esse valor padrão, ele não será serializado; não importa se foi atribuído explicitamente a zero / falso / cadeia vazia vs nunca atribuído
  • por esse motivo, não há conceito de "obrigatório", pois "atribui explicitamente um valor zero" e "nunca atribuiu um valor" parecem idênticos

No proto3, é possível criar um local com meio backup, mas perfeitamente válido, não fornecendo um dos campos obrigatórios.

O outro valor é: zero. O fato de você não atribuí-lo explicitamente a zero é discutível. Se você deseja ou não isso é com você, mas faz sentido para mim e é como muitas "inicializar um novo objeto / estrutura" funcionam em uma ampla variedade de plataformas.

Não é pior mover código de validação extra para cada cliente, verificando se todos os campos obrigatórios têm valores válidos?

Não há nada para validar! O layout é exatamente o que seria se o valor zero fosse atribuído explicitamente. Se isso é legal, é legal. Se é ilegal (porque zero não faz sentido para você), é ilegal; mas seria ilegal se fosse explícito ou implícito. A quantidade de validação envolvida não muda.

Isso não é uma grande desvantagem ao criar um formato de serialização baseado em esquema para a troca de dados entre clientes?

Geralmente não, não ... especialmente porque a versão do esquema é explícita. Se você deseja usar proto2: use proto2. Nada muda automaticamente.

Marc Gravell
fonte
Eu me pergunto o que "apenas o zero natural como padrão" os compra, pois o protobuf não é realmente utilizável sem algum tipo de esquema. Garantir padrões consistentes não parece muito mais difícil do que garantir esquemas consistentes em primeiro lugar.
CodesInChaos
1
@CodesInChaos isso é interessante, porque eu tenho feito o protobuf sem esquema por ... bem, para sempre :) no protobuf-net, espera-se que a maioria dos usuários seja o primeiro e o menos o esquema. E interessante (pelo menos para mim) a maioria das estratégias padrão "mantenha as coisas simples e estúpidas" que o protobuf-net usa são exatamente as mesmas que o proto3 optou por usar. Eu não vou afirmar que este valida as minhas decisões partidárias aleatórios, mas ... é totalmente faz :)
Marc Gravell
Considero uma classe C # um tipo de esquema e você certamente pode especificar valores padrão por meio de atributos. Compare isso com, por exemplo, msgpack ou json, que pode criar uma estrutura de dados significativa sem nenhum tipo de esquema.
CodesInChaos
@CodesInChaos concordou e observou - e sim, protobuf-net vai observar e respeitar quaisquer dessas declarações
Marc Gravell