プロトコルバッファ3で必須およびオプションが削除された理由


214

最近使っgRPCているproto3、私は気づいたrequiredoptional新しい構文で削除されました。

必須/オプションが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;
}

回答:


388

の有用性はrequired、多くの議論と炎上戦争の中心にあります。両側に大きなキャンプが存在しています。1つのキャンプは価値が存在することを保証するのが好きであり、その限界を受け入れて喜んででしたが、他のキャンプはrequired受け入れることを安全に追加または削除できないため危険または役に立たないていました。

requiredフィールドを慎重に使用する必要がある理由について詳しく説明します。すでにプロトを使用している場合、古いアプリケーションはそのフィールドを提供しておらず、アプリケーションは一般的に失敗をうまく処理できないため、必須フィールドを追加できません。すべての古いアプリケーションを最初にアップグレードすることを確認できますが、間違いを犯しやすく、プロトを任意のデータストア(memcachedなどの短期間のもの)に保存している場合は役に立ちません。必須フィールドを削除する場合も、同様の状況が当てはまります。

多くの必須フィールドは、「明らかに」必須となるまで...必須ではありませんでした。メソッドのidフィールドがあるとしますGet。それは明らかに必要です。ただし、後でidintを文字列に、またはint32をint64 に変更する必要がある場合があります。新しいmuchBetterIdフィールドを追加する必要あり、指定idする必要がある古いフィールドが残りますが、最終的には完全に無視されます。

これら2つの問題を組み合わせると、有益なrequiredフィールドの数が制限され、キャンプはそれがまだ価値があるかどうかについて議論します。の反対者requiredたちは必ずしもその考えに反対したわけではなく、その現在の形に反対していた。のrequiredようなより高度なものと一緒にチェックできるより表現力のある検証ライブラリを開発することを提案するname.length > 10一方で、より優れた障害モデルを持つことを確認しました。

Proto3は全体的に単純さを優先するようで、required削除はより単純です。しかし、おそらくより説得力のある、requiredプリミティブのフィールドプレゼンスの削除やオーバーライドするデフォルト値の削除など、他の機能と組み合わせると、proto3の削除は理にかなっています。

私はprotobuf開発者ではないので、この件に関して権威はありませんが、それでも説明が役立つことを願っています。


23
うん。:必要なフィールドを持つ恐ろしく間違って行くことができるもののこの拡張の説明も参照してくださいcapnproto.org/...
ケントンヴァルダ

8
オプションは削除されません。proto3ではすべてがオプションです。しかし、はい、フィールドの可視性(has_field)はプリミティブから削除されました。フィールドの可視性が必要な場合は、のようなメッセージを持つwrappers.protoを使用してくださいStringValue。メッセージなので、has_fieldを使用できます。これは事実上、多くの言語で一般的な「ボクシング」です。
エリックアンダーソン

9
逆に、proto3では「optional」が削除されたようです。すべてのフィールドが存在し、デフォルト値が入力されています。プリミティブフィールドがユーザーによって入力されたか、デフォルトで入力されたかを知る方法はありません。メッセージフィールドは基本的にポインタであり、null値を持つことができるという点でオプションです。
2017年

14
protobufは、炎の戦争を開始するために特別に設計された言語のように感じます
Randy L

5
ほとんどの人はAPIのバージョン管理をしたくないようです。「下位互換性」のためにすべてをオプションにする方が簡単です。
Holoceo 2018年

41

このprotobuf Githubの問題で説明を見つけることができます:

必須フィールドは一般に有害であり、protobufの互換性セマンティクスに違反していると考えられているため、proto3で必須フィールドを削除しました。protobufを使用する全体のアイデアは、新しい/古いバイナリと完全に前方/後方互換性を維持しながら、プロトコル定義からフィールドを追加/削除できることです。必須フィールドはこれを壊します。必須フィールドを.proto定義に安全に追加したり、既存の必須フィールドを安全に削除したりすることはできません。これは、これらのアクションの両方がワイヤの互換性を破壊するためです。たとえば、必須フィールドを.proto定義に追加すると、必須フィールドが古いデータに存在しないため、新しい定義でビルドされたバイナリは、古い定義を使用してシリアル化されたデータを解析できません。複雑なシステムで。プロト定義はシステムのさまざまなコンポーネントで広く共有されているため、必要なフィールドを追加/削除すると、システムの複数の部分が簡単にダウンする可能性があります。これによって何度も生産の問題が発生し、必要なフィールドを追加/削除することは、Googleのあらゆる場所でほぼ禁止されています。このため、proto3の必須フィールドを完全に削除しました。

「必須」を削除すると、「オプション」は冗長になるため、「オプション」も削除しました。


6
わかりません。逆シリアル化後と逆シリアル化時のメッセージのドロップの違いは何ですか?必要なフィールド(idなど)が含まれていないため、古いクライアントによってドロップされます。
Shmuel H.

6
@ShmuelHに同意する傾向があります。必須フィールドは、何らかの方法でAPIの一部になります。まあそれは両方の当事者に与えられた構文を通じて自動的にサポートされるか、バックエンドに隠されていますが、それはまだそこにあります。API定義で表示できるようにすることもできます
Cruncher

7
@ShmuelHに完全に同意します。フィールドはAPIで何らかの方法で必須であり、顧客がこれを知るのに役立ちます。これにより、まだバージョン管理をまだ行っていないように思います。
patrickbarker

6
@ShmuelHへの別の投票。後方互換性のない方法でAPIを変更した場合(必須フィールドを追加した場合)、パーサーにそれを検出させたいと思いますか?APIをバージョン管理してください!必要に応じて、Protobufで完全に実行することもできますoneof { MessageV1, MessageV2, etc. }
Timmmm

1
最初は必須フィールドがあることを正当化できませんでした。また、必須フィールドの追加は互換性のない変更であり、通常はプロトコルバージョンの変更(つまり、新しいメッセージタイプ)で処理する必要があります。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.