Почему требуется и необязательно удаляется в буфер протокола 3
Я недавно пользуюсь gRPC
с proto3
и я заметил, что required
а также optional
был удален в новом синтаксисе.
Кто-нибудь любезно объяснит, почему обязательные / необязательные удаляются в proto3? Подобные ограничения просто необходимы для того, чтобы сделать определение надежным.
Синтаксис proto2:
message SearchRequest {
required string query = 1;
optional int32 page_number = 2;
optional int32 result_per_page = 3;
}
Синтаксис proto3:
syntax = "proto3";
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
4 ответа
Полезность required
был в центре многих дебатов и пламенной войны. Большие лагеря существуют с обеих сторон. Один лагерь любил гарантировать наличие ценности и был готов жить со своими ограничениями, но другой чувствовал required
опасно или бесполезно, так как не может быть безопасно добавлено или удалено.
Позвольте мне объяснить больше причин, почему required
поля следует использовать с осторожностью. Если вы уже используете Proto, вы не можете добавить обязательное поле, потому что старое приложение не будет предоставлять это поле, а приложения в целом не справляются со сбоем. Вы можете убедиться, что все старые приложения обновляются первыми, но можно легко ошибиться, и это не поможет, если вы храните прототипы в любом хранилище данных (даже недолговечном, например, memcached). Такая же ситуация применяется при удалении обязательного поля.
Многие обязательные поля были "очевидно" обязательными, пока... их не было. Допустим, у вас есть id
поле для Get
метод. Это очевидно требуется. Кроме того, позже вам может понадобиться изменить id
от int до строки или от int32 до int64. Это требует добавления нового muchBetterId
поле, и теперь вы остались со старым id
поле, которое должно быть указано, но в конечном итоге полностью игнорируется.
Когда эти две проблемы объединены, число полезных required
поля становятся ограниченными, и лагеря спорят, имеет ли оно еще ценность. Противники required
не обязательно против идеи, но ее нынешней формы. Некоторые предлагали разработать более выразительную валидационную библиотеку, которая могла бы проверять required
наряду с чем-то более продвинутым, как name.length > 10
, также убедившись, что лучшая модель отказов.
Proto3 в целом, кажется, в пользу простоты, и required
удаление проще. Но может быть более убедительным, удаляя required
Имеет смысл для proto3 в сочетании с другими функциями, такими как удаление присутствия полей для примитивов и удаление переопределяющих значений по умолчанию.
Я не разработчик protobuf и никоим образом не авторитетен в этом вопросе, но я все еще надеюсь, что объяснение будет полезным.
Может быть, вы можете увидеть здесь
Мы удалили обязательные поля в proto3, потому что обязательные поля обычно считаются вредоносными и нарушающими семантику совместимости protobuf. Идея использования protobuf заключается в том, что он позволяет добавлять / удалять поля из определения протокола, при этом полностью совместимый с предыдущими / более старыми двоичными файлами. Обязательные поля нарушают это, хотя. Вы никогда не сможете безопасно добавить обязательное поле в определение.proto и не можете безопасно удалить существующее обязательное поле, поскольку оба эти действия нарушают совместимость проводов. Например, если вы добавите обязательное поле в определение.proto, двоичные файлы, созданные с новым определением, не смогут анализировать данные, сериализованные с использованием старого определения, поскольку обязательное поле отсутствует в старых данных. В сложной системе, где определения.proto широко используются многими различными компонентами системы, добавление / удаление обязательных полей может легко привести к отключению нескольких частей системы. Мы неоднократно сталкивались с производственными проблемами, и в Google практически никому не разрешалось добавлять / удалять обязательные поля. По этой причине мы полностью удалили обязательные поля в proto3.
После удаления "обязательного" "необязательного" просто избыточно, поэтому мы также удалили "необязательного".
Поскольку ортогональное разложение связанных концепций сложно, а дизайн протокольных буферов сочетает по крайней мере 4 отдельных концепции таким образом, что это вызывает разочарование: обнуление (также известное как отслеживание присутствия), проверка содержимого, полезные значения по умолчанию и эффективность использования пространства.
Proto2 позволял полям быть «обязательными» или «необязательными» и разрешал указывать значения по умолчанию, но только для «необязательных» полей.
Ключевое слово «необязательно» вернулось в 3.12/3.15 для использования в отслеживании присутствия. См. примечание к приложению в Field Presence.
Ключевое слово «required» было применено для проверки правильности, и это было просто неудачно, потому что Protobuf не соответствует задаче быть инструментом проверки. У него нет синтаксиса минимальных/максимальных значений, ограничений по длине или шаблону. Что еще более важно, в нем нет ничего для выражения зависимостей значений данных между полями (кроме отношений, присущих базовой структуре).
Protobuf использует значения «по умолчанию» для начальных значений конструкции и в качестве механизма для уменьшения размера сообщений, не отправляя эти значения (в proto3). Это немного прискорбно, потому что возможность указать начальное значение для конкретного прогона генерации кода была бы удобна как для производителя («это значение, которое я хочу отправить при обычном использовании»), так и для потребителя («может быть, я должен проверить на нуль/отсутствие, но на данный момент будет достаточно отступить, как если бы было отправлено «x» ").
OTOH, кажется, было бы полезно указать договорное предположение по умолчанию о том, как действовать, если значение не указано. Однако хорошая работа с этим часто зависит от значений (или наличия) других полей, и Protobuf не соответствует этому из-за той же (возможно, прекрасной) несложности, которая делает его непригодным для проверки данных. Поэтому, если вы хотите получить хорошее поведение при отсутствии полей, вам лучше сочетать явные проверки присутствия с любыми другими подходящими проверками данных. .... и по крайней мере в 3.12/3.15 и далее можно. ... и, возможно, нулевые значения достаточно хороши для упрощенных случаев.