Por qué se eliminan los requisitos obligatorios y opcionales en Protocol Buffers 3
Recientemente estoy usando gRPC
with proto3
y lo noté required
y optional
se 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;
}
La utilidad de required
ha 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 required
peligroso o inútil ya que no se puede agregar ni eliminar de manera segura.
Permítanme explicar más por qué required
los 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 id
campo para un Get
método. Obviamente esto es necesario. Excepto que, más adelante, es posible que necesites cambiar id
de int a string, o de int32 a int64. Eso requiere agregar un nuevo muchBetterId
campo, y ahora le queda el id
campo antiguo que debe especificarse, pero que eventualmente se ignora por completo.
Cuando esos dos problemas se combinan, el número de required
campos beneficiosos se vuelve limitado y los bandos discuten sobre si todavía tienen valor. Los oponentes required
no 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 required
junto 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 required
la eliminación es más sencilla. Pero tal vez sea más convincente que la eliminación required
tuviera 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.
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".
Los campos opcionales fueron devueltos en protobuf 3.15
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.