Por qué se eliminan los requisitos obligatorios y opcionales en Protocol Buffers 3

Resuelto yjzhang asked hace 9 años • 4 respuestas

Recientemente estoy usando gRPCwith proto3y lo noté requiredy optionalse eliminó en una nueva sintaxis.

¿Alguien tendría la amabilidad de explicar por qué se eliminan los requisitos/opcionales en proto3? Este tipo de restricciones parecen necesarias para que la definición sea sólida.

sintaxis proto2:

message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3;
}

sintaxis proto3:

syntax = "proto3";
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}
yjzhang avatar Aug 04 '15 12:08 yjzhang
Aceptado

La utilidad de requiredha estado en el centro de muchos debates y guerras. Han existido grandes campos en ambos lados. A un bando le gustaba garantizar que un valor estuviera presente y estaba dispuesto a vivir con sus limitaciones, pero el otro bando se sentía requiredpeligroso o inútil ya que no se puede agregar ni eliminar de manera segura.

Permítanme explicar más por qué requiredlos campos deben usarse con moderación. Si ya está utilizando un proto, no puede agregar un campo obligatorio porque las aplicaciones antiguas no proporcionarán ese campo y las aplicaciones en general no manejan bien la falla. Puede asegurarse de que todas las aplicaciones antiguas se actualicen primero, pero puede ser fácil cometer un error y no ayuda si está almacenando los prototipos en cualquier almacén de datos (incluso de corta duración, como Memcached). El mismo tipo de situación se aplica al eliminar un campo obligatorio.

Muchos campos obligatorios eran "obviamente" obligatorios hasta que... dejaron de serlo. Digamos que tienes un idcampo para un Getmétodo. Obviamente esto es necesario. Excepto que, más adelante, es posible que necesites cambiar idde int a string, o de int32 a int64. Eso requiere agregar un nuevo muchBetterIdcampo, y ahora le queda el idcampo antiguo que debe especificarse, pero que eventualmente se ignora por completo.

Cuando esos dos problemas se combinan, el número de requiredcampos beneficiosos se vuelve limitado y los bandos discuten sobre si todavía tienen valor. Los oponentes requiredno estaban necesariamente en contra de la idea, sino de su forma actual. Algunos sugirieron desarrollar una biblioteca de validación más expresiva que pudiera verificar requiredjunto con algo más avanzado como name.length > 10, al mismo tiempo que se aseguraba de tener un mejor modelo de falla.

En general, Proto3 parece favorecer la simplicidad y requiredla eliminación es más sencilla. Pero tal vez sea más convincente que la eliminación requiredtuviera sentido para proto3 cuando se combina con otras características, como la eliminación de la presencia de campos para primitivas y la eliminación de valores predeterminados primordiales.

No soy un desarrollador de protobuf y de ninguna manera tengo autoridad en el tema, pero todavía espero que la explicación sea útil.

Eric Anderson avatar Aug 04 '2015 16:08 Eric Anderson

Puedes encontrar la explicación en este número de protobuf Github :

Eliminamos los campos obligatorios en proto3 porque los campos obligatorios generalmente se consideran dañinos y violan la semántica de compatibilidad de protobuf. La idea general de usar protobuf es que le permite agregar/eliminar campos de su definición de protocolo y al mismo tiempo ser totalmente compatible con versiones anteriores y anteriores de binarios más nuevos/antiguos. Sin embargo, los campos obligatorios rompen esto. Nunca podrá agregar de forma segura un campo obligatorio a una definición .proto, ni podrá eliminar de forma segura un campo obligatorio existente porque ambas acciones rompen la compatibilidad de cables. Por ejemplo, si agrega un campo obligatorio a una definición .proto, los archivos binarios creados con la nueva definición no podrán analizar los datos serializados utilizando la definición anterior porque el campo requerido no está presente en los datos antiguos. En un sistema complejo donde las definiciones de .proto se comparten ampliamente entre muchos componentes diferentes del sistema, agregar o eliminar campos obligatorios podría fácilmente desactivar varias partes del sistema. Hemos visto problemas de producción causados ​​por esto varias veces y está prácticamente prohibido en todas partes dentro de Google que cualquiera agregue o elimine campos obligatorios. Por este motivo eliminamos por completo los campos obligatorios en proto3.

Después de eliminar "obligatorio", "opcional" es simplemente redundante, por lo que también eliminamos "opcional".

maiyang avatar Sep 17 '2018 02:09 maiyang

Los campos opcionales fueron devueltos en protobuf 3.15

z0mb1ek avatar Mar 17 '2021 13:03 z0mb1ek

Porque la factorización ortogonal de conceptos relacionados es difícil y el diseño de Protocol Buffers combinó al menos 4 conceptos separados de una manera que se volvió frustrante: nulabilidad (también conocida como seguimiento de presencia), validación de contenido, valores predeterminados útiles y eficiencia del espacio.

Proto2 permitía que un campo fuera " obligatorio" u "opcional" y permitía especificar valores predeterminados, pero sólo para campos "opcionales".

La palabra clave "opcional" volvió en 3.12/3.15 para usarse en el seguimiento de presencia. Consulte la nota de la aplicación sobre presencia en el campo .

La palabra clave "requerido" se aplicó como verificación de validación y eso fue simplemente desafortunado porque Protobuf no está a la altura de la tarea de ser una herramienta de validación. No tiene restricciones de patrón, longitud o sintaxis de valor mínimo/máximo. Más importante aún, no tiene nada para expresar dependencias de valores de datos entre campos (aparte de las relaciones intrínsecas a la estructura básica).

Protobuf utiliza valores 'predeterminados' para los valores de construcción iniciales y como mecanismo para reducir el tamaño de los mensajes al no enviar esos valores (en proto3). Esto es un poco desafortunado porque poder especificar un valor inicial para una ejecución de generación de código particular sería útil tanto para un productor ("este es el valor que quiero enviar en mi uso normal") como para un consumidor ("tal vez debería verifique si hay nulo o no está presente, pero retroceder como si se hubiera enviado 'x' será suficiente por ahora ").

OTOH, parece que sería útil especificar un supuesto contractual predeterminado sobre cómo proceder si no se proporciona un valor. Sin embargo, hacer un buen trabajo a menudo depende de los valores (o presencia) de otros campos y Protobuf no está a la altura por la misma (posiblemente hermosa) falta de complejidad que lo hace inadecuado para la validación de datos. Por lo tanto, si desea tener un buen comportamiento frente a los campos faltantes, lo mejor es combinar comprobaciones de presencia explícitas con otras comprobaciones de datos que sean apropiadas. .... y al menos en 3.12/3.15 en adelante puedes hacerlo. ... y tal vez los valores 0-ish sean lo suficientemente buenos para los casos simplistas.

SensorSmith avatar Oct 15 '2022 00:10 SensorSmith