Protocol Buffers Developer Guide - Overview（和訳）

## これはなに
[Proto3 Language Guide の和訳](https://qiita.com/CyLomw/items/9aa4551bd6bb9c0818b6) はすでに別の方がやってくださっていたけれど、
Protocol Buffers Developer Guide - Overview の日本語訳がなかったので翻訳してみました。
ドキュメントは翻訳時点(2019/11/18)で最新のものを使用しています。その後の変更によりこの翻訳の内容と本体のドキュメントで齟齬が発生する可能性があるのでご注意ください。

また、この Protocol Buffers Developer Guide は proto2 を前提に書かれているようですので(現在の最新版は proto3 )混乱しないよう、御留意ください。

原文： https://developers.google.com/protocol-buffers/docs/overview

ライセンス: 
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

## Developer Guide
protocol buffers の開発者向けドキュメントへようこそ。protocol buffers は言語に依存せず、プラットフォームに依存せず、通信プロトコルやデータストレージなどで使用するために構造化データをシリアライズする拡張可能な手段です。

このドキュメントは、自身のアプリケーションで protocol buffers を使用したい Java, C++, または Python 開発者を対象としています。 この概要では、protocol buffers を紹介し、使用し始めるために必要なことを説明します。その後、[チュートリアル](https://developers.google.com/protocol-buffers/docs/tutorials)に進んだり、 [protocol buffers encoding](https://developers.google.com/protocol-buffers/docs/encoding) の詳細を掘り下げることができます。 API  [reference documentation](https://developers.google.com/protocol-buffers/docs/reference/overview) では、3つの言語すべて、および  `.proto` ファイルを作成するための[言語](https://developers.google.com/protocol-buffers/docs/proto)および[スタイルガイド](https://developers.google.com/protocol-buffers/docs/style)について言及します。

訳者注: 本文中には reference documentation の提供は3言語とされていますが(おそらく proto2 の対応言語が上記3言語なため)、翻訳時点で公開されている proto3 では、 C++, Dart, Go, Java, Python, Ruby, C#, Objective C, Javascript, PHP の10言語と、 protocol buffers の API リファレンスが提供されています。

## protocol buffers とは？
protocol buffers は、構造化データをシリアライズするための柔軟で効率的な自動化メカニズムです。 XML と比較してみても、小さく、速く、そしてシンプルです。一度データを構造化する方法を定義したら、特別に生成されたソースコードを使用して、構造化データをさまざまなデータストリームとさまざまな言語で簡単に読み書きできます。 「古い」フォーマットでコンパイルされたデプロイ済みプログラムを壊すことなく、データ構造を更新することもできます。

## protocol buffers はどう機能するのか
`.proto` ファイルで protocol buffer のメッセージタイプを定義することにより、シリアライズする情報をどのように構造化するかを指定します。 各 protocol buffer のメッセージは、一連の名前と値のペアを含む情報の小さな論理レコードです。 以下は、個人 (Person) に関する情報を含むメッセージを定義する `.proto` ファイルの非常に基本的な例です。

```protobuf
message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;
}
```

ご覧のように、メッセージフォーマットはシンプルです。各メッセージタイプには1つ以上の一意の番号付きフィールドがあり、各フィールドには名前と値の型を定義します。値の型には数値（整数または浮動小数点）、ブール値、文字列、生のバイト、または（上記の例のように）他の protocol buffers のメッセージタイプでさえも使用することができ、それらを用いてデータを階層的に構造化することができます。また、オプションフィールド、[必須フィールド](https://developers.google.com/protocol-buffers/docs/proto#required_warning)、および繰り返しフィールドも指定することができます。 `.proto` ファイルの作成に関する詳細については、[Protocol Buffer Language Guide](https://developers.google.com/protocol-buffers/docs/proto) を参照してください。

メッセージの定義が終わると、 `.proto` ファイルに対しアプリケーションで使用している言語の protocol buffer コンパイラを実行して、データアクセスクラスを生成することができます。これらは各フィールドに単純なアクセサー ( `name()` や `set_name()` など) や、構造全体を生バイトにシリアライズしたり、生のバイトをパースするメソッドを提供します。例えば、選択した言語が C++ の場合、上記の例では、 `Person` というクラスがコンパイラにより生成されます。その後、アプリケーションでこのクラスを使用して、 `Person` の protocol buffer メッセージを生成、シリアライズ、および取得できます。例えば次のようなものです。

```c++
Person person;
person.set_name("John Doe");
person.set_id(1234);
person.set_email("jdoe@example.com");
fstream output("myfile", ios::out | ios::binary);
person.SerializeToOstream(&output);
```

その後、下記のようにメッセージを読み戻すことができます。

```c++
fstream input("myfile", ios::in | ios::binary);
Person person;
person.ParseFromIstream(&input);
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
```

後方互換性を損なうことなく、メッセージフォーマットに新しいフィールドを追加できます。 古いバイナリは、パース時に新しいフィールドを単に無視します。 そのため、データ形式として protocol buffers を使用する通信プロトコルがある場合、既存のコードを壊すことを心配せずにプロトコルを拡張できます。

生成された protocol buffer のコードを使用するための完全なリファレンスは [API リファレンスセクション](https://developers.google.com/protocol-buffers/docs/reference/overview)にあり、 [Protocol Buffer Encoding](https://developers.google.com/protocol-buffers/docs/encoding) で  protocol buffer のメッセージがどのようにエンコードされているかについて詳しく知ることができます。

## なぜ XML を使用しないのか
protocol buffers には、構造化データのシリアライズに関してXMLよりも多くの利点があります。 protocol buffers は：

- よりシンプルで
- 3〜10倍小さく
- 20〜100倍高速で
- 曖昧さが少なく
- プログラミング的により使いやすいデータアクセスクラスを生成します

たとえば、 `name` と `email` を使用して `person` をモデル化するとします。 XMLでは、次のように記載する必要があります。

```xml
<person>
  <name>John Doe</name>
  <email>jdoe@example.com</email>
</person>
```

一方、対応する protocol buffer のメッセージ（ protocol buffer [テキスト形式](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.text_format) の定義を使用）は次のとおりです。

```protobuf
# protocol buffer のテキスト表現です。
# これは、ワイヤーで使用されるバイナリ形式ではありません.
person {
  name: "John Doe"
  email: "jdoe@example.com"
}
```

このメッセージが protocol buffer の[バイナリ形式](https://developers.google.com/protocol-buffers/docs/encoding)にエンコードされている場合（上記のテキスト形式は、デバッグと編集に便利な、人間が読める形式にすぎません）、おそらく28バイトで、パースに約100-200ナノ秒かかります。 XML のバージョンは空白を削除した場合でも、少なくとも69バイトあり、解析には約5,000〜10,000ナノ秒かかります。

また、下記のように protocol buffer の操作の方がはるかに簡単です。

```c++
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
```

一方、XMLでは次のようにする必要があります。

```c++
cout << "Name: "
     << person.getElementsByTagName("name")->item(0)->innerText()
     << endl;
cout << "E-mail: "
     << person.getElementsByTagName("email")->item(0)->innerText()
     << endl;
```

ただし、 protocol buffers は常に XML よりも優れたソリューションであるというわけではありません。たとえば、 protocol buffers は、構造をテキストで簡単にインターリーブできないため、マークアップ（HTMLなど）を使用してテキストベースのドキュメントをモデリングするのに適した方法ではありません。 さらに、 XML は人間が読み書きすることができます。 ネイティブ形式の protocol buffers は少なくともそうではありません。 XML はまた、ある程度まで自己記述的でもあります。 protocol buffers は、メッセージ定義（ `.proto` ファイル）がある場合にのみ意味をなします。


## これは私が探していたものだ！どうやったら始められる？
[パッケージをダウンロード](https://developers.google.com/protocol-buffers/docs/downloads.html)します。これには、 Java, Python および C++ の protocol buffer コンパイラの完全なソースコードと、 I/O およびテストに必要なクラスが含まれています。 コンパイラをビルドしてインストールするには、 README の指示に従ってください。

設定が完了したら、選択した言語の[チュートリアル](https://developers.google.com/protocol-buffers/docs/tutorials)に従ってください。これにより、 protocol buffer を使用する簡単なアプリケーションを作成できます。

## proto3 の紹介
最新のバージョン3の[リリース](https://github.com/protocolbuffers/protobuf/releases)では、新しい言語バージョンである Protocol Buffers 言語バージョン3（別名 proto3）、および既存の言語バージョン（別名 proto2）にいくつかの新機能が導入されています。 Proto3 は、より使いやすく、またより幅広いプログラミング言語で利用できるように、 protocol buffer 言語を簡素化しています。現在のリリースでは、Java, C++, Python, Java Lite, Ruby, JavaScript, Objective- C および C＃ の protocol buffer コードが生成できます。さらに、 [golang/protobuf](https://github.com/golang/protobuf) Githubリポジトリから入手できる最新の Go protoc プラグインを使用して、 Go の proto3 コードが生成できます。より多くの言語がパイプラインにあります。

2つの言語バージョンの API は完全には互換性がないことに注意してください。既存のユーザーへの不便を避けるため、新しい protocol buffer のリリースでは以前の言語バージョンを引き続きサポートします。

[リリースノート](https://github.com/protocolbuffers/protobuf/releases)で現在のデフォルトバージョンとの主な違いを確認し、 [Proto3 Language Guide](https://developers.google.com/protocol-buffers/docs/proto3) で proto3 の構文について学習できます。 proto3 の完全なドキュメントはまもなく提供されます！

(proto2 と proto3 の名前が少し紛らわしいように思えるのは、元々 protocol buffer をオープンソース化したとき、実際には proto2 としても知られる Google の2番目のバージョンであったためです。また、これがオープンソースのバージョン番号が v2.0.0 から始まった理由でもあります。)

訳者注: 本文中には、 `proto3 の完全なドキュメントはまもなく提供されます！` とありますが、一見 [Proto3 Language Guide](https://developers.google.com/protocol-buffers/docs/proto3) で提供されているものは、十分に完全なドキュメントと呼べるものな気がします。こちらのドキュメントのアップデートが追いついていないのかもしれません。

## ちょっとした歴史
protocol buffers は、インデックスサーバーのリクエスト/レスポンスのプロトコルを処理するために Google で最初に開発されました。 protocol buffers の前には、リクエストとレスポンスのハンドマーシャリング/アンマーシャリングを使用し、プロトコルの多くのバージョンをサポートするリクエストとレスポンスの形式がありました。 これにより、次のような非常に醜いコードが生成されていました。

```c++
 if (version == 3) {
   ...
 } else if (version > 4) {
   if (version == 5) {
     ...
   }
   ...
 }
```

明示的にフォーマットされたプロトコルは、新しいプロトコルバージョンのロールアウトも複雑にしました。開発者は、スイッチを切り替えて新しいプロトコルの使用を開始する前に、リクエストの発信者とリクエストを処理する実際のサーバーの間のすべてのサーバーが、新しいプロトコルを理解することを確認する必要があるためです。

Protocol buffers は、次のような問題の多くを解決するために設計されました。

- 新しいフィールドを簡単に導入でき、データを検査する必要のない中間サーバーは、すべてのフィールドについて知る必要なく、単にデータをパースしてデータを通過させることができる。
- フォーマットはより自己記述的であり、さまざまな言語 （C++, Java など）で処理できる。

ただし、ユーザーはパースのためのコードを自身で手書きする必要がありました。

システムが進化するにつれて、次のような他の多くの機能と用途を獲得しました。

- 自動生成されたシリアライズおよびデシリアライズコードにより、手動でパースする必要がなくなった。
- 短命のRPC(Remote Procedure Call)リクエストに使用されることに加えて、人々はデータを永続的に格納するための便利な自己記述形式として(たとえば、 Bigtable で) protocol buffers を使用し始めた。
- プロトコルコンパイラーが生成するスタブクラスを使用して、サーバーのRPCインターフェースはプロトコルファイルの一部として宣言され始めた。(ユーザーはスタブクラスを、サーバーのインターフェースの実際の実装でオーバーライドすることができた)

protocol buffers は現在、データのための Google での共通語です。執筆時点では、348,952個の `.proto` ファイルにわたり、 Google コードツリーで306,747種類のメッセージタイプが定義されています。 これらは RPC システムと、さまざまなストレージシステムにおけるデータの永続的なストレージの両方で使用されています。


---

## 終わりに
Google のドキュメントそのものに対し、日本語訳のプルリクエストなどを出すことができなかったので、Qiitaにまとめてみました。やる気が出たら、他のドキュメントも翻訳してみようと思います。