protocol buffersで値を段階的にdeprecatedにしていく方法

結論

  • はじめにfield optionであるdeprecatedを定義
  • 完全に使われていないことを確認したらReservedfieldを使い、廃止する

具体的なシチュエーション

  • 例えばgolang製のAPIとAndroidアプリ間で、protocol buffersを用いて以下のようなMessageTypeを定義しているとします
syntax = "proto3";

message SearchRequest {
  string queyr = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}
  • 値1がqueyrとなっていますが、誰も気づかずにAPI・アプリともにリリースまでしてしまったとします

version upのタイミングで[deprecated=true]を加える

  • ここで例えばAndroidエンジニアが「次のアプリであるversion2のアプリでは、queyrを直してqueryと定義したい」と決めたとします
syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}
  • しかし上記のように定義を変更してはいけません
    • 何故ならversion1のアプリがqueyrという定義を使えなくなってしまうからです
  • 間違った定義は古いversionのアプリのために残しておき、新しい値を定義しましょう
syntax = "proto3";

message SearchRequest {
  string queyr = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
  string query = 4;
}
  • version2のアプリではqueryを使用するコードを実装し、API側ではqueyr, queryのどちらの値がリクエストされても対応できるように変更します
  • また、ここで登場するのが冒頭に述べた「field optionであるdeprecated」です、上記の定義は以下のように変更してみます
syntax = "proto3";

message SearchRequest {
  string queyr = 1 [deprecated=true];
  int32 page_number = 2;
  int32 result_per_page = 3;
  string query = 4;
}

deprecated (field option): If set to true, indicates that the field is deprecated and should not be used by new code. In most languages this has no actual effect. In Java, this becomes a @Deprecated annotation. In the future, other language-specific code generators may generate deprecation annotations on the field's accessors, which will in turn cause a warning to be emitted when compiling code which attempts to use the field. If the field is not used by anyone and you want to prevent new users from using it, consider replacing the field declaration with a reserved statement.

例えば強制バージョンアップのタイミングでReservedを使う

  • さてアプリの開発も捗り、version3のAndroidアプリが完成しました
    • 新機能をたくさん盛り込んで、全ユーザーにversion3を使ってもらいたい状態です
    • APIでアプリのversionを管理できるようにしておいたので、version1, 2のアプリを使っているユーザーにアプリのアップデートを促した、とします
  • ここで、version1用の定義であるqueyrは使われなくなりました
    • 完全に廃止するために以下のように変更するとします
syntax = "proto3";

message SearchRequest {
  Reserved 1; // string queyr = 1 [deprecated=true];
  int32 page_number = 2;
  int32 result_per_page = 3;
  string query = 4;
}

If you update a message type by entirely removing a field, or commenting it out, future users can reuse the tag number when making their own updates to the type. This can cause severe issues if they later load old versions of the same .proto, including data corruption, privacy bugs, and so on. One way to make sure this doesn't happen is to specify that the field tags (and/or names, which can also cause issues for JSON serialization) of your deleted fields are reserved. The protocol buffer compiler will complain if any future users try to use these field identifiers.

  • Reserved 1;という表記だけでも十分です
    • ただ、「廃止以前は何のための値だったのか」という情報が欠落するため、上記に示した通り以前の定義はコメントにしておくとベターかなと個人的に思います
  • これにて値1は完全に廃止、ということにすることが出来ました

再度結論

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.