[JAVA] Comment gérer facultatif dans les tampons de protocole (proto3)

Les tampons de protocole ont été supprimés de «obligatoire» et «facultatif» dans proto3. En ce qui concerne le contexte de la suppression, voir @qsona Entrée pour un résumé facile à comprendre. Je vous remercie.

Le problème est que dans proto3, chaque champ a une valeur par défaut, donc le champ avec la valeur par défaut est du côté de l'utilisateur.

  1. «Une valeur similaire à la valeur par défaut intentionnellement définie»
  2. Valeur par défaut non définie car elle n'existe pas Cela signifie que vous ne pouvez pas non plus juger.

En d'autres termes, comment exprimer une valeur facultative.

Comment exprimer en option

Il existe plusieurs options, mais la réponse de Stack Overflow est utile. Sera.

  1. Dans un champ distinct, exprimer explicitement la présence ou l'absence

schema.proto


message User {
  int32 id = 1;
  bool has_name = 2; //Indique la présence ou l'absence de nom
  string name = 3;   //Valeur actuelle
}

Example(Java)


User user1 = User.newBuilder()
		.setHasName(true)
		.setName("Tom")
		.build();

User user2 = User.newBuilder()
		.setHasName(false) //La valeur par défaut est false, vous n'avez donc pas réellement besoin d'un ensemble
		.build();

user1.getHasName(); // true
user1.getName();    // "Tom"

user2.getHasName(); // false
user2.getName();    // ""
  1. Utilisez l'un des

schema.proto


message User {
  int32 id = 1;
  oneof name_optional {
    string name = 2; //Enveloppez la valeur de traitement avec l'un des
  }
}

Example(Java)


User user1 = User.newBuilder()
		.setName("Tom")
		.build();
User user2 = User.newBuilder()
		.build();

user1.getNameOptionalCase(); // User.NameOptionalCase.NAME
user1.getName();             // "Tom"

user2.getNameOptionalCase(); // User.NameOptionalCase.NAMEOPTIONAL_NOT_SET
user2.getName();             // ""
  1. Utilisez google / protobuf / wrappers.proto

schema.proto


message User {
  int32 id = 1;
  google.protobuf.StringValue name = 2;
}

Example(Java)


User user1 = User.newBuilder()
		.setName(StringValue.newBuilder().setValue("Tom").build())
		.build();
User user2 = User.newBuilder()
		.build();

user1.hasName();            // true
user1.getName().getValue(); // "Tom"

user2.hasName();            // false
user2.getName().getValue(); // ""

Considération

La première chose que nous avons tous en commun est que quelle que soit l'option que vous choisissez, vous ne pouvez pas la forcer à être une valeur facultative. * 1 Par conséquent, pour toute option, il est nécessaire d'effectuer de manière procédurale «vérifier l'existence» → «traiter la valeur».

En 1, la notation est très simple, mais le compilateur ne peut garantir la relation entre les deux champs, et il est nécessaire de la supporter avec des commentaires.

Par rapport à 1, 2 a l'avantage de pouvoir exprimer la présence ou l'absence de champs au niveau du compilateur, mais c'est un usage un peu étrange de l'un des domaines où plusieurs champs sont supposés.

3 est intuitif et facile à utiliser lorsqu'il s'agit de valeurs optionnelles, mais il présente également certains inconvénients.

Exemple:

schema.proto


message User {
  int32 id = 1;
  Fullname fullname = 2;
}

message Fullname {
  string first_name = 1;
  string last_name = 2;
}

Par exemple, dans un tel cas, le wrapper n'est fourni qu'avec les types suivants, il ne peut donc pas être utilisé si vous souhaitez rendre chaque nom complet facultatif.

DoubleValue
FloatValue
Int64Value
UInt64Value
Int32Value
UInt32Value
BoolValue
StringValue
BytesValue

Par conséquent, si vous souhaitez unifier des expressions facultatives, il est facile de comprendre unifier avec 1 ou 2.

Résumé

Protocol Buffers est un langage de schéma avec des spécifications compactes et se caractérise par de faibles coûts d'apprentissage et une bonne lisibilité. Cependant, pour cette raison, certaines expressions communes à d'autres ont été supprimées, et je pense que davantage d'expressions peuvent être créées en les utilisant tout en les couvrant en temps opportun.

Recommended Posts

Comment gérer facultatif dans les tampons de protocole (proto3)
Comment gérer les fichiers TSV et les fichiers CSV dans Ruby
Comment utiliser java Facultatif
Comment gérer les instances
Comment gérer les exceptions froidement avec Java 8 Stream ou en option
Différences dans la gestion des chaînes entre Java et Perl
Comment utiliser Lombok au printemps
Comment trouver May'n dans XPath
Comment masquer la barre de défilement dans WebView
Comment exécuter JUnit dans Eclipse
Comment itérer indéfiniment en Ruby
Comment exécuter Ant dans Gradle
Comment maîtriser la programmation en 3 mois
Comment apprendre JAVA en 7 jours
Comment obtenir des paramètres dans Spark
Comment installer Bootstrap dans Ruby
Comment utiliser InjectorHolder dans OpenAM
Comment installer jQuery dans Rails 6
Comment utiliser les classes en Java?
Comment nommer des variables en Java
Comment définir Lombok dans Eclipse
Comment concaténer des chaînes avec Java
Comment installer Swiper in Rails
[swift5] Comment spécifier la couleur en hexadécimal
Comment implémenter la fonctionnalité de recherche dans Rails
Comment implémenter le calcul de la date en Java
Comment implémenter le filtre de Kalman par Java
Prise en charge multilingue de Java Comment utiliser les paramètres régionaux
Comment utiliser le volume nommé dans docker-compose.yml
Comment filtrer JUnit Test dans Gradle
Comment insérer une vidéo dans Rails
[java] Résumé de la gestion des caractères
Comment normaliser le pied de page d'en-tête dans Thymeleaf
Comment inclure Spring Tool dans Eclipse 4.6.3?
Comment ajouter un fichier jar dans ScalaIDE
Comment faire une conversion de base en Java
Comment avoir des paramètres dans la méthode link_to
Comment utiliser MySQL dans le didacticiel Rails
Remplacez List <Optional <T >> par Optional <List <T >> en Java
Comment fixer la date système dans JUnit
Comment appliquer les conventions de codage en Java
Comment intégrer Janus Graph dans Java
[rails] Comment configurer le routage dans les ressources
Comment obtenir la date avec Java
Comment gérer les erreurs de connexion avec l'appareil
Comment implémenter la fonctionnalité de classement dans Rails
Comment utiliser les variables d'environnement dans RubyOnRails
Comment implémenter le traitement asynchrone dans Outsystems
Comment publier une bibliothèque dans jCenter
Comment spécifier l'attribut id dans JSF
Comprendre en 5 minutes !! Comment utiliser Docker
Comment écraser les données Firebase avec Swift
Comment utiliser credentials.yml.enc introduit à partir de Rails 5.2